- Keyword arguments make the intention of a function call more clear
- Use Keyword-only arguments to force callers to supply keyword arguments for potentially confusing functions, especially those that accept multiple Boolean
- Python 3 supports explicit syntax for keyword-only arguments in functions
- Python 2 can emulate keyword-only arguments for functions by using **kwargs and munually rasising TypeError
Effective Python
Divide one number by another but be another but be very careful about special cases. Sometimes you want to ignore ZeoroDivisionError
exceptions and return infinity instead. Other times, you want to ignore OverflowError
exceptions and return zero instead.
def safe_division(number, divisor, ignore_overflow, ignore_zero_division):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return float('inf')
else:
raise
Using this function is strightforward.
safe_division(1, 0, True, False)
The problem is that it's easy to confuse the position of the two Boolean arguments that control the exception-ignoring behavior. This can easily cause bugs that are hard to track down. One way to improve this readability of this code is to use keyword arguments.
def safe_division_b(number, divisor,
ignore_overflow=False,
ignore_zero_division=False):
pass
safe_division_b(1, 10**500, ignore_overflow=True)
safe_division_b(1, 0, ignore_zero_division=True)
However, since these keyword arguments are optional behavior, there's nothing forcing callers of your functions to use keyword arguments for clarity.
safe_division_b(1, 0, True, False)
In Python3, you can demand clartiy by defining your functions with keyword-only arguments. These arguments can only be supplied by keyword, never by position. Here, I redefine the safe_division functions to accept keyword-only arguments. The *
symbol in the argument list indicates the end of positional arguments and the beginning of keyword-only arguments.
def safe_division_c(number, divisor, *,
ignore_overflow=False,
ignore_zero_division=False):
pass
safe_division_c(1, 10**500, True, False)
safe_division_c(1, 10 **500, True, False)
TypeError: safe_division_c() takes 2 positional arguments but 4 were given