class Klass:
def __init__(self, **kwargs):
self.func(variable=True, **kwargs)
def func(self, variable=True, **kwargs):
print(variable)
if __name__ == '__main__':
Klass(variable=False)
I was wondering why I am getting TypeError: func() got multiple values for keyword argument 'variable'
.
I am thinking it should print False
because I override the default value of variable
to False
and pass kwargs
along the way.
You can't pass the same argument twice, and variable=True, **kwargs
does exactly that when kwargs
contains a key for variable
; in this case, you made the call effectively self.func(variable=True, variable=False)
which is clearly wrong. Assuming you can't receive variable
as a separate argument, e.g.:
def __init__(self, variable=True, **kwargs):
self.func(variable, **kwargs)
# On Python 3, you can easily keep variable keyword-only with:
def __init__(self, *, variable=True, **kwargs):
self.func(variable, **kwargs)
# while the Python 2 equivalent for keyword-only args is rather nastier:
def __init__(self, *positional_forbidden, variable=True, **kwargs):
if positional_forbidden:
raise TypeError("__init__ takes 1 positional argument but {} were given".format(len(positional_forbidden)+1))
self.func(variable, **kwargs)
then the other approach is to set the default in the kwargs
dict
itself:
def __init__(self, **kwargs):
kwargs.setdefault('variable', True) # Sets variable to True only if not passed by caller
self.func(**kwargs)
In Python 3.5, with PEP 448's additional unpacking generalizations, you could one-line this safely as:
def __init__(self, **kwargs):
self.func(**{'variable': True, **kwargs})
because repeated keys are legal when creating a new dict
(only the last occurrence of a key is kept), so you can create a brand new dict
with unique mappings, then immediately unpack it.