Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forcing keyword arguments in python 2.7

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.

like image 448
Elise Avatar asked Dec 06 '25 10:12

Elise


1 Answers

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.

like image 149
Anthon Avatar answered Dec 08 '25 09:12

Anthon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!