Reputation: 7418
Say I have the following function, which makes a call to another function:
def f1(arg1, arg2, arg3):
f2(...)
The arguments of f1
and f2
are the same, or f2
might look like this:
def f2(**kwargs)
pass # whatever
The client code is going to define and call f1
, and it is required that the signature of f1
explicitly defines all arguments, and thus no **kwargs
is allowed for f1
.
So, to make a call to f2
from inside f1
I have to do this:
def f1(arg1, arg2, arg3):
f2(arg1, arg2, arg3)
Is there a way I can pass arguments to f2
without explicitly writing them? Ideally, I think it should look like this:
def f1(arg1, arg2, arg3):
kwargs = <Some Magic Here>
f2(**kwargs)
Any magic?
UPDATE
Is there a way I can combine locals()
and inspect.getargspec()
to aggregate my **kwargs
?
Upvotes: 4
Views: 2766
Reputation: 90889
Well, you can create kwargs
as a dictionary of all the arguments that f2()
accepts and pass it. Though I do not see any benefit from that, using -
def f1(arg1, arg2, arg3):
f2(arg1=arg1, arg2=arg2, arg3=arg3)
Looks fine to me , and would be easier than building the dictionary and calling it as **kwargs
.
Anyway the way to do it is -
>>> def a(a,b,c):
... kwargs = {'a':a , 'b':b , 'c':c}
... d(**kwargs)
...
>>> def d(**kwargs):
... print(kwargs)
...
>>> a(1,2,3)
{'c': 3, 'a': 1, 'b': 2}
The problem is that f1 is going to be defined by the client, the processing of argument is common for all, so I want to hide the processing details, so that the client passes all the arguments to the implementation. Furthermore, I want to ease the definition and automatically pass all arguments and not specify them explicitly.
locals()
inside a function returns you the copy of the local variables in the function at that time as a dictionary. If as in your question if the definition of f1()
and f2()
are same you can use locals()
, by calling it at the start of the function before any other code. Example -
>>> def a(a,b,c):
... lcl = locals()
... print(lcl)
... d(**lcl)
... e = 123
... print(locals())
...
>>> def d(**kwargs):
... print(kwargs)
...
>>> a(1,2,3)
{'c': 3, 'a': 1, 'b': 2}
{'c': 3, 'a': 1, 'b': 2}
{'c': 3, 'a': 1, 'e': 123, 'lcl': {...}, 'b': 2}
Upvotes: 3
Reputation: 7418
Here is how I solved my problem based on Anand S Kumar's answer as well as Alex Martelli's answer to another question:
def f2():
kwargs = inspect.getouterframes(inspect.currentframe(), 2)[1][0].f_locals
print(kwargs)
def f1(arg1, arg2, arg3)
f2() # this should be called right at the first line
>>> f1(1, 2, 3)
{'arg1': 1, 'arg2': 2, 'arg3': 3}
Upvotes: 1
Reputation: 107287
What you want here is passing the arguments of the parent function to an enclosing function.So fist I must say that you can not use local()
because local
is contain the local variables which is contain the argument and all local variables that you have define in your function buddy, but if you just want to get all the arguments when they are dynamic and like your example, I suggest to use *args
in parents function :
def f1(*args):
But there is a point here, since you want to use **kwargs
and it is for collecting the arbitrarily keyword arguments you need to initial names of your argument.
For example you can use a dict comprehension like following :
def f1(*args):
kwargs = {'arg{}'.format(i):j for i,j in enumerate(args,1)}
f2(**kwargs)
Also if you are sure that there is no local variable in your function buddy specially before defining the enclosing function you can use locals
:
Example :
>>> globsl_a=8
>>> def fun(arg1,arg2,arg3):
... print locals()
...
>>> fun(5,[3,4],'text')
{'arg1': 5, 'arg2': [3, 4], 'arg3': 'text'}
>>>
Upvotes: 1