# 163. Using functools.partial for Function Customization

**Snippet 1: Freezing One Argument in a Function**

```python
from functools import partial

# Function that adds two numbers
def add(a, b):
    return a + b

# Freeze the value of 'a' to 10
add_10 = partial(add, 10)

# Call the partially frozen function
result = add_10(5)  # This will add 10 + 5
print(f"Result: {result}")
```

***

**Snippet 2: Freezing Multiple Arguments**

```python
from functools import partial

# Function that adds three numbers
def add_three(a, b, c):
    return a + b + c

# Freeze 'a' to 5 and 'b' to 10
add_5_and_10 = partial(add_three, 5, 10)

# Call the partially frozen function
result = add_5_and_10(15)  # This will add 5 + 10 + 15
print(f"Result: {result}")
```

***

**Snippet 3: Customizing a Logging Function**

```python
from functools import partial

# General logging function
def log(message, level="INFO"):
    print(f"[{level}] {message}")

# Create a 'WARNING' logger
log_warning = partial(log, level="WARNING")

# Call the customized logger
log_warning("This is a warning message.")
```

***

**Snippet 4: Freezing Function Arguments for Custom Operations**

```python
from functools import partial

# Function to multiply two numbers
def multiply(x, y):
    return x * y

# Freeze 'x' to 2, creating a function that doubles the input
double = partial(multiply, 2)

# Call the customized function
result = double(5)  # This will double 5 (2 * 5)
print(f"Result: {result}")
```

***

**Snippet 5: Customizing a Power Function**

```python
from functools import partial

# Function to raise a number to a given power
def power(base, exponent):
    return base ** exponent

# Freeze the exponent to 3, creating a cube function
cube = partial(power, exponent=3)

# Call the customized function
result = cube(4)  # This will compute 4^3
print(f"Result: {result}")
```

***

**Snippet 6: Freezing Keyword Arguments**

```python
from functools import partial

# Function that greets a user with a specific message
def greet(name, message="Hello"):
    print(f"{message}, {name}!")

# Freeze the message to "Good Morning"
greet_morning = partial(greet, message="Good Morning")

# Call the customized function
greet_morning("Alice")
```

***

**Snippet 7: Customizing Function for Different Operations**

```python
from functools import partial

# Function to apply a given operation to two numbers
def apply_operation(x, y, operation):
    return operation(x, y)

# Freeze operation to addition
add = partial(apply_operation, operation=lambda x, y: x + y)

# Call the customized function
result = add(3, 4)  # This will add 3 and 4
print(f"Result: {result}")
```

***

**Snippet 8: Partial Function with Default Arguments**

```python
from functools import partial

# Function to multiply two numbers with a default factor
def multiply_by_factor(x, factor=2):
    return x * factor

# Freeze factor to 5, creating a function to multiply by 5
multiply_by_5 = partial(multiply_by_factor, factor=5)

# Call the customized function
result = multiply_by_5(4)  # This will multiply 4 by 5
print(f"Result: {result}")
```

***

**Snippet 9: Customizing a String Formatter**

```python
from functools import partial

# Function to format a string
def format_string(template, name, age):
    return template.format(name=name, age=age)

# Freeze the template string
greeting = partial(format_string, template="Hello, my name is {name} and I am {age} years old.")

# Call the customized function
result = greeting(name="John", age=30)
print(result)
```

***

**Snippet 10: Freezing Arguments in a File Reading Function**

```python
from functools import partial

# Function to read lines from a file with specific encoding
def read_file(file_path, encoding="utf-8"):
    with open(file_path, 'r', encoding=encoding) as f:
        return f.read()

# Freeze encoding to 'ascii'
read_file_ascii = partial(read_file, encoding="ascii")

# Call the customized function (assuming 'file.txt' exists)
# result = read_file_ascii("file.txt")
# print(result)
```

***
