I know I can use * to force all keyword arguments to a function/method to be "named".
If I have
def abc(a, *, x=10, z=30):
pass
then the following all work
abc(5)
abc(8, x=12)
abc(9, z=31)
abc(x=17, a=4)
even if I change the function signature to def abc(a, *, x=10, y=20, z=30),
and
abc(7, 13)
throws an error.
This is extremely important because, I can use the logical place, which will help maintenance over time, without being forced to use the end position based on history.
But * is not valid in Python 2.7, and abc(a, *args, x=10, z=30) (which I tried) doesn't work either.
Is there a way to force the use of x=12 in Python 2.7? Or another way of saying: make abc(7, 13) be invalid on Python 2.7.
One way of doing this is by adding a dummy keyword argument that never gets a valid positional value (so don't check for None):
_dummy = object()
def abc(a, dummy_kw=_dummy, x=10, z=30):
if dummy_kw is not _dummy:
raise TypeError("abc() takes 1 positional argument but at least 2 were given")
That will prohibit abc(7, 13) and allow all the others. It works on Python 2 and Python 3, so it is useful when you have code that needs to run on both.
Originally I used:
def _dummy():
pass
but as @mata pointed out _dummy=object() works as well, and cleaner. Essentially any unique memory location that is not used in another way will work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With