
Mastering Python Functions: Writing Clean and Reusable Code
Defining and Calling Functions
In Python, a function is defined using the def keyword, followed by the function name and a set of parentheses. Inside the parentheses, you can define parameters that the function accepts. The function body is indented and contains the logic that executes when the function is called.
def greet(name):
return f"Hello, {name}!"To call the function:
print(greet("Alice")) # Output: Hello, Alice!Default Arguments and Optional Parameters
Python allows you to define default values for function parameters, making them optional. This is useful when you want to provide a sensible fallback if a parameter is not supplied.
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"Now, the function can be called in multiple ways:
print(greet("Alice")) # Output: Hello, Alice!
print(greet("Bob", "Hi")) # Output: Hi, Bob!Best Practice: Always place parameters with default values after those without. This prevents confusion and syntax errors.
Keyword-Only Arguments
In Python 3, you can enforce that certain parameters must be passed by keyword. This improves code clarity and prevents accidental misuse.
def connect(host, *, port, timeout=10):
return f"Connecting to {host}:{port} with timeout {timeout}"In this case, port is a keyword-only argument. You must call the function like this:
connect("example.com", port=8080) # Valid
connect("example.com", 8080) # Invalid, raises TypeErrorFunction Annotations
Function annotations provide metadata about the expected types of parameters and return values. They are not enforced at runtime but can improve code documentation and support tools like type checkers.
def add(a: int, b: int) -> int:
return a + bAnnotations do not affect the function's behavior but are useful for IDEs and static analysis tools.
| Feature | Description |
|---|---|
def keyword | Defines a function |
| Default args | Optional parameters with default values |
* parameter | Enforces keyword-only arguments |
| Annotations | Type hints for better code clarity |
Variable-Length Arguments
Python allows functions to accept variable numbers of arguments using args (for positional arguments) and *kwargs (for keyword arguments).
def log_message(*args, **kwargs):
message = ' '.join(str(arg) for arg in args)
level = kwargs.get('level', 'info')
return f"[{level.upper()}] {message}"Example usage:
log_message("User logged in", user="Alice", level="debug")
# Output: [DEBUG] User logged inTip: Useargsand*kwargssparingly. Overuse can make functions harder to understand and test.
Returning Multiple Values
Python functions can return multiple values as a tuple, which is particularly useful for decomposing results.
def divmod_custom(a, b):
quotient = a // b
remainder = a % b
return quotient, remainderUsage:
q, r = divmod_custom(10, 3)
print(q, r) # Output: 3 1Function Best Practices
- Keep functions focused: One function should perform one task.
- Use descriptive names: Avoid
func1,do_this, or similar vague names. - Avoid side effects: A function should ideally return a value without modifying external state.
- Document with docstrings: Provide a clear explanation of the function’s purpose, parameters, and return value.
Example docstring:
def factorial(n: int) -> int:
"""
Calculate the factorial of a non-negative integer.
Args:
n (int): The number to compute the factorial of.
Returns:
int: The factorial of n.
Raises:
ValueError: If n is negative.
"""
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
result = 1
for i in range(2, n + 1):
result *= i
return result