Safe Argument Patterns
Recommended Strategies for Default Arguments
Safe argument patterns help prevent unexpected behavior and make your Python code more predictable and maintainable.
Pattern 1: None as Default Marker
def process_data(data=None):
if data is None:
data = []
## Process the data safely
return [x * 2 for x in data]
## Safe usage
print(process_data()) ## []
print(process_data([1, 2, 3])) ## [2, 4, 6]
Pattern 2: Immutable Default Arguments
graph TD
A[Default Argument] --> B{Type}
B --> |Immutable| C[Safe to Use]
B --> |Mutable| D[Potential Risk]
Recommended Immutable Types
Type |
Example |
Safe Usage |
None |
None |
Always safe |
Integer |
0 |
Predictable |
String |
"" |
Consistent |
Tuple |
() |
Immutable |
Pattern 3: Factory Function for Complex Defaults
def create_config(options=None):
def get_default_options():
return {
"debug": False,
"timeout": 30,
"retries": 3
}
if options is None:
options = get_default_options()
return options
## Safe configuration handling
config1 = create_config()
config2 = create_config({"debug": True})
Advanced Pattern: Type Hints and Default Values
from typing import List, Optional
def process_items(
items: Optional[List[int]] = None,
multiplier: int = 1
) -> List[int]:
if items is None:
items = []
return [item * multiplier for item in items]
## Type-safe and flexible
print(process_items()) ## []
print(process_items([1, 2, 3], 2)) ## [2, 4, 6]
Key Best Practices
- Use
None
as a default marker
- Initialize mutable objects inside the function
- Prefer immutable default values
- Use type hints for clarity
When to Use Each Pattern
graph TD
A[Choose Pattern] --> B{Argument Type}
B --> |Simple Value| C[Immutable Default]
B --> |Complex Object| D[None + Factory]
B --> |Collection| E[None + Initialization]
At LabEx, we recommend these patterns to write clean, predictable, and maintainable Python code that avoids common pitfalls with default arguments.