Reputation: 11934
What is a cleaner way to check if an argument was passed in by position or by keyword?
I am cloning and overriding functions under certain circumstances. The signatures of the overridden functions may grow over time, so I want something I won't have to change later, that I can use to extract only the couple of parameters I care about and ignore all the rest.
For example, the function call may look like this:
foo("bar", "baz")
foo(arg1="bar", arg2="baz")
Both are valid. If I am using args
and kwargs
to catch all the parameters, I have to figure out which one it ended up in. So far I'm doing this:
def foo(*args, **kwargs):
arg1 = kwargs["arg1"] if "arg1" in kwargs else args[0]
arg2 = kwargs["arg2"] if "arg2" in kwargs else args[1]
I feel like there has to be a cleaner way to do this.
Upvotes: 1
Views: 1099
Reputation: 13069
You could do:
def foo(*args, **kwargs):
argnames = ["arg1", "arg2"]
argdict = dict(zip(argnames, args))
argdict.update(kwargs)
print(argdict)
foo("bar", "baz")
foo(arg1="bar", arg2="baz")
Both give the same:
{'arg1': 'bar', 'arg2': 'baz'}
{'arg1': 'bar', 'arg2': 'baz'}
Then if you really need you can do arg1 = argdict["arg1"]
etc, but you might as well just use a dictionary rather than extract into named variables.
(Using string constants "bar"
and "baz"
here, rather than bar
and baz
, for sake of a self-contained example, but it is not dependent on them being strings.)
Upvotes: 2