Related
In a similar way to using varargs in C or C++:
fn(a, b)
fn(a, b, c, d, ...)
Yes. You can use *args as a non-keyword argument. You will then be able to pass any number of arguments.
def manyArgs(*arg):
print "I was called with", len(arg), "arguments:", arg
>>> manyArgs(1)
I was called with 1 arguments: (1,)
>>> manyArgs(1, 2, 3)
I was called with 3 arguments: (1, 2, 3)
As you can see, Python will unpack the arguments as a single tuple with all the arguments.
For keyword arguments you need to accept those as a separate actual argument, as shown in Skurmedel's answer.
Adding to unwinds post:
You can send multiple key-value args too.
def myfunc(**kwargs):
# kwargs is a dictionary.
for k,v in kwargs.iteritems():
print "%s = %s" % (k, v)
myfunc(abc=123, efh=456)
# abc = 123
# efh = 456
And you can mix the two:
def myfunc2(*args, **kwargs):
for a in args:
print a
for k,v in kwargs.iteritems():
print "%s = %s" % (k, v)
myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123
They must be both declared and called in that order, that is the function signature needs to be *args, **kwargs, and called in that order.
If I may, Skurmedel's code is for python 2; to adapt it to python 3, change iteritems to items and add parenthesis to print. That could prevent beginners like me to bump into:
AttributeError: 'dict' object has no attribute 'iteritems' and search elsewhere (e.g. Error “ 'dict' object has no attribute 'iteritems' ” when trying to use NetworkX's write_shp()) why this is happening.
def myfunc(**kwargs):
for k,v in kwargs.items():
print("%s = %s" % (k, v))
myfunc(abc=123, efh=456)
# abc = 123
# efh = 456
and:
def myfunc2(*args, **kwargs):
for a in args:
print(a)
for k,v in kwargs.items():
print("%s = %s" % (k, v))
myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123
Adding to the other excellent posts.
Sometimes you don't want to specify the number of arguments and want to use keys for them (the compiler will complain if one argument passed in a dictionary is not used in the method).
def manyArgs1(args):
print args.a, args.b #note args.c is not used here
def manyArgs2(args):
print args.c #note args.b and .c are not used here
class Args: pass
args = Args()
args.a = 1
args.b = 2
args.c = 3
manyArgs1(args) #outputs 1 2
manyArgs2(args) #outputs 3
Then you can do things like
myfuns = [manyArgs1, manyArgs2]
for fun in myfuns:
fun(args)
def f(dic):
if 'a' in dic:
print dic['a'],
pass
else: print 'None',
if 'b' in dic:
print dic['b'],
pass
else: print 'None',
if 'c' in dic:
print dic['c'],
pass
else: print 'None',
print
pass
f({})
f({'a':20,
'c':30})
f({'a':20,
'c':30,
'b':'red'})
____________
the above code will output
None None None
20 None 30
20 red 30
This is as good as passing variable arguments by means of a dictionary
Another way to go about it, besides the nice answers already mentioned, depends upon the fact that you can pass optional named arguments by position. For example,
def f(x,y=None):
print(x)
if y is not None:
print(y)
Yields
In [11]: f(1,2)
1
2
In [12]: f(1)
1
In the following function, args[i] should unpack into the arguments of the function func via the * before it, however what gets passed in is a list. What am I missing?
def mymap(func, *seq):
args = list(zip(seq))
ret = []
for i in range(len(args)):
print(type(args[i]))
ret.append( func(*args[i]) )
return ret
f = lambda x: x+2
mymap(f, [1,2,3])
The * packs in a function definition and unpacks in a function call.
Defining a new function:
def func1(*args):
print(args)
this packs:
>>> func1(1, 2)
(1, 2)
A function with two parameters
def func2(a, b):
print(a)
print(b)
can be called with a sequence using the *:
>>> func2(*[1, 2])
1
2
How can I check if a function can always be called with the same arguments as another function? For example, b can be called with all arguments provided to a.
def a(a, b, c=None):
pass
def b(a, *args, d=4,**kwargs):
pass
The reason I want this is that I have a base function:
def f(a, b):
print('f', a, b)
and a list of callbacks:
def g(b, a):
print('g', a, b)
def h(*args, **kwargs):
print('h', args, kwargs)
funcs = [g, h]
and a wrapper function that accepts anything:
def call(*args, **kwargs):
f(*args, **kwargs)
for func in funcs:
func(*args, **kwargs)
Now I want to check if all callbacks will accept the arguments provided to call(), assuming they're valid for f().
For performance reasons, I don't want to check the arguments every time call() is called, but rather check each callback before adding it to the list of callbacks.
For example, those calls are ok:
call(1, 2)
call(a=1, b=3)
But this one should fail because g has arguments in wrong order:
call(1, b=3)
This took a bit of fun research, but i think i've covered the corner cases. A number of them arise to keep things compatible with python 2 while new syntax being added.
Most problematic part is the fact that some named (keyword) parameters can be passed in as positional argument or be required based on order passed in.
For more see comments.
Below code will ensure that function b can be called using any possible combination of valid arguments to function a. (does not imply inverse).
Uncomment/add try except block to get true/valse result and not an AssertionError.
import inspect
def check_arg_spec(a,b):
"""
attrs of FullArgSpec object:
sp.args = pos or legacy keyword arguments, w/ keyword at back
sp.varargs = *args
sp.varkw = **kwargs
sp.defaults = default values for legacy keyword arguments #
sp.args
sp.kwdonly = keyword arguments follow *args or *, must be passed in by name
sp.kwdonlydefaults = {name: default_val, .... }
sp.annotatons -> currently not in use, except as standard flag for outside applications
Consume order:
(1) Positional arguments
(2) legacy keyword argument = default (can be filled by both keyword or positional parameter)
[
(3) *args
[
(4) keyword only arguments [=default]
]
]
(5) **kwds
"""
a_sp = inspect.getfullargspec(a)
b_sp = inspect.getfullargspec(b)
kwdfb = b_sp.kwonlydefaults or {}
kwdfa = a_sp.kwonlydefaults or {}
kwddefb = b_sp.defaults or []
kwddefa = a_sp.defaults or []
# try:
akwd = a_sp.kwonlyargs
if len(kwddefa):
akwd += a_sp.args[-len(kwddefa):]
bkwd = b_sp.kwonlyargs
if len(kwddefb):
bkwd += b_sp.args[-len(kwddefb):]
# all required arguments in b must have name match in a spec.
for bkey in (set(b_sp.args) ^ set(bkwd)) & set(b_sp.args) :
assert bkey in a_sp.args
# all required positional in b can be met by a
assert (len(a_sp.args)-len(kwddefb)) >= (len(b_sp.args)-len(kwddefb))
# if a has *args spec, so must b
assert not ( a_sp.varargs and b_sp.varargs is None )
# if a does not take *args, max number of pos args passed to a is len(a_sp.args). b must accept at least this many positional args unless it can consume *args
if b_sp.varargs is None:
# if neither a nor b accepts *args, check that total number of pos plus py2 style keyword arguments for sg of b is more than a can send its way.
assert len(a_sp.args) <= len(b_sp.args)
# Keyword only arguments of b -> they are required, must be present in a.
akws = set(a_sp.kwonlyargs) | set(a_sp.args[-len(kwddefa):])
for nmreq in (set(b_sp.kwonlyargs)^set(kwdfb)) & set(b_sp.kwonlyargs):
assert nmreq in akws
# if a and b both accept an arbitrary number of positional arguments or if b can but a cannot, no more checks neccessary here
# if a accepts optional arbitrary, **kwds, then so must b
assert not (a_sp.varkw and b_sp.varkw is None)
if b_sp.varkw is None:
# neither a nor b can consume arbitrary keyword arguments
# then b must be able to consume all keywords that a can be called w/th.
for akw in akwd:
assert akw in bkwd
# if b accepts **kwds, but not a, then there is no need to check further
# if both accept **kwds, then also no need to check further
# return True
#
# except AssertionError:
#
# return False
Not sure what you are really looking for and I'm pretty sure your issue could be solved in a better way, but anyway:
from inspect import getargspec
def foo(a, b, c=None):
pass
def bar(a, d=4, *args, **kwargs):
pass
def same_args(func1, func2):
return list(set(getargspec(func1)[0]).intersection(set(getargspec(func2)[0])))
print same_args(foo, bar)
# => ['a']
same_args just check arguments from func1 and func2 and returns a new list with only same arguments in both func1 and func2.
In a similar way to using varargs in C or C++:
fn(a, b)
fn(a, b, c, d, ...)
Yes. You can use *args as a non-keyword argument. You will then be able to pass any number of arguments.
def manyArgs(*arg):
print "I was called with", len(arg), "arguments:", arg
>>> manyArgs(1)
I was called with 1 arguments: (1,)
>>> manyArgs(1, 2, 3)
I was called with 3 arguments: (1, 2, 3)
As you can see, Python will unpack the arguments as a single tuple with all the arguments.
For keyword arguments you need to accept those as a separate actual argument, as shown in Skurmedel's answer.
Adding to unwinds post:
You can send multiple key-value args too.
def myfunc(**kwargs):
# kwargs is a dictionary.
for k,v in kwargs.iteritems():
print "%s = %s" % (k, v)
myfunc(abc=123, efh=456)
# abc = 123
# efh = 456
And you can mix the two:
def myfunc2(*args, **kwargs):
for a in args:
print a
for k,v in kwargs.iteritems():
print "%s = %s" % (k, v)
myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123
They must be both declared and called in that order, that is the function signature needs to be *args, **kwargs, and called in that order.
If I may, Skurmedel's code is for python 2; to adapt it to python 3, change iteritems to items and add parenthesis to print. That could prevent beginners like me to bump into:
AttributeError: 'dict' object has no attribute 'iteritems' and search elsewhere (e.g. Error “ 'dict' object has no attribute 'iteritems' ” when trying to use NetworkX's write_shp()) why this is happening.
def myfunc(**kwargs):
for k,v in kwargs.items():
print("%s = %s" % (k, v))
myfunc(abc=123, efh=456)
# abc = 123
# efh = 456
and:
def myfunc2(*args, **kwargs):
for a in args:
print(a)
for k,v in kwargs.items():
print("%s = %s" % (k, v))
myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123
Adding to the other excellent posts.
Sometimes you don't want to specify the number of arguments and want to use keys for them (the compiler will complain if one argument passed in a dictionary is not used in the method).
def manyArgs1(args):
print args.a, args.b #note args.c is not used here
def manyArgs2(args):
print args.c #note args.b and .c are not used here
class Args: pass
args = Args()
args.a = 1
args.b = 2
args.c = 3
manyArgs1(args) #outputs 1 2
manyArgs2(args) #outputs 3
Then you can do things like
myfuns = [manyArgs1, manyArgs2]
for fun in myfuns:
fun(args)
def f(dic):
if 'a' in dic:
print dic['a'],
pass
else: print 'None',
if 'b' in dic:
print dic['b'],
pass
else: print 'None',
if 'c' in dic:
print dic['c'],
pass
else: print 'None',
print
pass
f({})
f({'a':20,
'c':30})
f({'a':20,
'c':30,
'b':'red'})
____________
the above code will output
None None None
20 None 30
20 red 30
This is as good as passing variable arguments by means of a dictionary
Another way to go about it, besides the nice answers already mentioned, depends upon the fact that you can pass optional named arguments by position. For example,
def f(x,y=None):
print(x)
if y is not None:
print(y)
Yields
In [11]: f(1,2)
1
2
In [12]: f(1)
1
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 9 years ago.
Does * have a special meaning in Python as it does in C? I saw a function like this in the Python Cookbook:
def get(self, *a, **kw)
Would you please explain it to me or point out where I can find an answer (Google interprets the * as wild card character and thus I cannot find a satisfactory answer).
See Function Definitions in the Language Reference.
If the form *identifier is
present, it is initialized to a tuple
receiving any excess positional
parameters, defaulting to the empty
tuple. If the form **identifier is
present, it is initialized to a new
dictionary receiving any excess
keyword arguments, defaulting to a new
empty dictionary.
Also, see Function Calls.
Assuming that one knows what positional and keyword arguments are, here are some examples:
Example 1:
# Excess keyword argument (python 2) example:
def foo(a, b, c, **args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args
foo(a="testa", d="excess", c="testc", b="testb", k="another_excess")
As you can see in the above example, we only have parameters a, b, c in the signature of the foo function. Since d and k are not present, they are put into the args dictionary. The output of the program is:
a = testa
b = testb
c = testc
{'k': 'another_excess', 'd': 'excess'}
Example 2:
# Excess positional argument (python 2) example:
def foo(a, b, c, *args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args
foo("testa", "testb", "testc", "excess", "another_excess")
Here, since we're testing positional arguments, the excess ones have to be on the end, and *args packs them into a tuple, so the output of this program is:
a = testa
b = testb
c = testc
('excess', 'another_excess')
You can also unpack a dictionary or a tuple into arguments of a function:
def foo(a,b,c,**args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)
argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo(**argdict)
Prints:
a=testa
b=testb
c=testc
args={'excessarg': 'string'}
And
def foo(a,b,c,*args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)
argtuple = ("testa","testb","testc","excess")
foo(*argtuple)
Prints:
a=testa
b=testb
c=testc
args=('excess',)
I only have one thing to add that wasn't clear from the other answers (for completeness's sake).
You may also use the stars when calling the function. For example, say you have code like this:
>>> def foo(*args):
... print(args)
...
>>> l = [1,2,3,4,5]
You can pass the list l into foo like so...
>>> foo(*l)
(1, 2, 3, 4, 5)
You can do the same for dictionaries...
>>> def foo(**argd):
... print(argd)
...
>>> d = {'a' : 'b', 'c' : 'd'}
>>> foo(**d)
{'a': 'b', 'c': 'd'}
All of the above answers were perfectly clear and complete, but just for the record I'd like to confirm that the meaning of * and ** in python has absolutely no similarity with the meaning of similar-looking operators in C.
They are called the argument-unpacking and keyword-argument-unpacking operators.
A single star means that the variable 'a' will be a tuple of extra parameters that were supplied to the function. The double star means the variable 'kw' will be a variable-size dictionary of extra parameters that were supplied with keywords.
Although the actual behavior is spec'd out, it still sometimes can be very non-intuitive. Writing some sample functions and calling them with various parameter styles may help you understand what is allowed and what the results are.
def f0(a)
def f1(*a)
def f2(**a)
def f3(*a, **b)
etc...
I find * useful when writing a function that takes another callback function as a parameter:
def some_function(parm1, parm2, callback, *callback_args):
a = 1
b = 2
...
callback(a, b, *callback_args)
...
That way, callers can pass in arbitrary extra parameters that will be passed through to their callback function. The nice thing is that the callback function can use normal function parameters. That is, it doesn't need to use the * syntax at all. Here's an example:
def my_callback_function(a, b, x, y, z):
...
x = 5
y = 6
z = 7
some_function('parm1', 'parm2', my_callback_function, x, y, z)
Of course, closures provide another way of doing the same thing without requiring you to pass x, y, and z through some_function() and into my_callback_function().