Let's say you want to write a comparator function that takes two objects.
def is_newer(older, newer):
return older.timestamp < newer.timestamp
def keep_newer(file1, file2):
if is_newer(file1, file2):
os.unlink(file1)
else:
os.unlink(file2)
The function name is_newer()
is ambiguous whether the first or second argument is considered the "newer" one.
Reviewers of the function keep_newer()
cannot trivially verify that the logic is correct
without looking up the internals of is_newer()
.
In Python 3, you can use keyword-only parameters to force callers to name required parameters.
def is_newer(*, older, newer):
# Everything after * must be a keyword parameter.
return older.timestamp < newer.timestamp
def keep_newer(file1, file2):
if is_newer(older=file1, newer=file2):
os.unlink(file1)
else:
os.unlink(file2)
Now, someone who reads keep_newer()
has a pretty good idea of what is going on
at the point what is now a self-documenting function call. It's overkill to
use this everywhere, but can be useful when extra clarity is needed.
In Python 2, you could get close with keyword arguments:
def is_newer(older=None, newer=None):
assert older is not None
assert newer is not None
return older.timestamp < newer.timestamp
However, it's not quite as clean, and there might not be illegal default values that make sense in every case.
- Reference: Python 3 Glossary, search for "keyword-only"
- Also a StackOverflow answer on this topic.