Javascript has a poorly constructed but convenient "arguments" variable inside every function, such that you can pass arguments through a function like so:
function foo(a, b, c) {
return bar.apply(this, arguments);
}
function bar(a, b, c) {
return [a, b, c];
}
foo(2, 3, 5); // returns [2, 3, 5]
Is there an easy way to do a similar thing in Python?
4 Answers 4
>>> def foo(*args):
... return args
>>> foo(1,2,3)
(1,2,3)
is that what you want?
3 Comments
*args functionality behaves the way that spread and rest are anticipated for the next Javascript standardization.foo(a=1, b=2) you can capture them using the ** keyword expansion: foo(**kwargs) which gives you kwargs as a dict and any dict can be sent to another function as keyword arguments via bar(**kwargs)foo(a, b, *args) or foo(a, b=None, **kargs) or even, in python 3, foo(a, b, *args, c=None, **kargs)Yeah, this is what I should have said.
def foo(*args):
return bar(*args)
You don't need to declare the function with (a,b,c). bar(...) will get whatever foo(...) gets.
My other crummier answer is below:
I was so close to answering "No, it can't easily be done" but with a few extra lines, I think it can. @cbrauchli great idea using locals(), but since locals() also returns local variables, if we do
def foo(a,b,c):
n = "foobar" # any code that declares local variables will affect locals()
return bar(**locals())
we'll be passing an unwanted 4th argument, n, to bar(a,b,c) and we'll get an error. To solve this, you'd want to do something like arguments = locals() in the very first line i.e.
def foo(a, b, c):
myargs = locals() # at this point, locals only has a,b,c
total = a + b + c # we can do what we like until the end
return bar(**myargs) # turn the dictionary of a,b,c into a keyword list using **
How about using * for argument expansion?
>>> def foo(*args):
... return bar(*(args[:3]))
>>> def bar(a, b, c):
... return [a, b, c]
>>> foo(1, 2, 3, 4)
[1, 2, 3]
3 Comments
def foo(a, b, c): return bar(*(args[:3]))locals() in foo. locals().values() would give you all of the args passed to foo but they wouldn't be in a consistent order.I think this most closely resembles your javascript snippet. It doesn't require you to change the function definition.
>>> def foo(a, b, c):
... return bar(**locals())
...
>>> def bar(a, b, c):
... return [a, b, c]
...
>>> foo(2,3,5)
[2, 3, 5]
Note that locals() gets all of the local variables, so you should use it at the beginning of the method and make a copy of the dictionary it produces if you declare other variables. Or you can use the inspect module as explained in this SO post.