Reputation: 1003
Let's say I have a function f()
which I know accepts 1 argument, action
, followed by a variable number of arguments.
Depending on the initial action
value, the function expects a different set of following arguments, e.g. for action 1
we know we must have 3 extra arguments p1
, p2
and p3
. Depending on how the function was called, these args can be either in args
or `kwargs.
How do I retrieve them?
def f(action, *args, **kwargs):
if action==1:
#we know that the function should have 3 supplementary arguments: p1, p2, p3
#we want something like:
#p1 = kwargs['p1'] OR args[0] OR <some default> (order matters?)
#p1 = kwargs['p1'] OR args[0] OR <some default>
#p1 = kwargs['p1'] OR args[0] OR <some default>
Note that:
f(1, 3, 4, 5)
f(1,p1=3, p2=4, p3=5)
f(1, 2, p2=4, p3=5)
will place the different p1
, p2
, p3
parameters in either args
or kwargs
. I could try with nested try/except statements, like:
try:
p1=kwargs['p1']
except:
try:
p1=args[0]
except:
p1=default
but it does not feel right.
Upvotes: 1
Views: 1675
Reputation: 552
You can try with, using OrderedDict:
from collections import OrderedDict
def f(action, *args, **kwargs):
params = OrderedDict({
'p1': 'default',
'p2': 'default',
'p3': 'default',
})
if action == 1:
for index, param in enumerate(params.keys()):
if index < len(args):
params[param] = kwargs[param] if param in kwargs else args[index]
else:
params[param] = kwargs[param] if param in kwargs else params[param]
# Do something with `params`.
f(1, 3, 4, 5)
f(1, p1=3, p2=4, p3=5)
f(1, 2, p2=4, p3=5)
If you need more parameters, just add them to the ordered dictionary.
Upvotes: 1
Reputation: 21
I feel you were quite close to the answer on your question in out of itself. You can do something like this:
def f(action, *args, **kwargs):
if action==1:
p1=kwargs.get('p1') or args[0] if len(args)>0 else 'default'
...
The order does matter. In this case if you the key arguments would take priority over positional ones.
Here are some input examples --> value of p1 in the function:
f(1,10)
-->10f(1,2,20)
-->2f(1,p1=10)
-->10f(1,10,p1=2)
-->2f(1,p3=20)
-->'default'Upvotes: 2
Reputation: 1914
I would call a sub-function with a defined argument list within f
:
def f(action, *args, **kwargs):
if action == 1:
f_1(*args, **kwargs)
...
def f_1(p1, p2, p3):
# now you know the args
Of course, this raises the question why you need the over-all function, but let's assume you have a reason for that ;). Else, you could also have a dictionary:
funcs = {1: f_1, 2: ....}
Then you can call the correct function with individual arguments as
funcs[action](p1, p2, p3)
Upvotes: 3