Python3 keyword-only arguments ( * ) can be modeled in python2.x with **kwargs
Consider the following python3 code:
def f(pos_arg, *, no_default, has_default='default'): print(pos_arg, no_default, has_default)
and his behavior:
>>> f(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() takes 1 positional argument but 3 were given >>> f(1, no_default='hi') 1 hi default >>> f(1, no_default='hi', has_default='hello') 1 hi hello >>> f(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() missing 1 required keyword-only argument: 'no_default' >>> f(1, no_default=1, wat='wat') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() got an unexpected keyword argument 'wat'
This can be modeled using the following, mind you, I took the liberty of switching TypeError to KeyError in the case of “named argument required”, it would not be too much work to make this type the same exception, but
def f(pos_arg, **kwargs): no_default = kwargs.pop('no_default') has_default = kwargs.pop('has_default', 'default') if kwargs: raise TypeError('unexpected keyword argument(s) {}'.format(', '.join(sorted(kwargs)))) print(pos_arg, no_default, has_default)
And the behavior:
>>> f(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() takes exactly 1 argument (3 given) >>> f(1, no_default='hi') (1, 'hi', 'default') >>> f(1, no_default='hi', has_default='hello') (1, 'hi', 'hello') >>> f(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f KeyError: 'no_default' >>> f(1, no_default=1, wat='wat') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in f TypeError: unexpected keyword argument(s) wat
The recipe works just as well in Python3.x, but it should be avoided if you are only Python3.x