[python] Can a variable number of arguments be passed to a function?

In a similar way to using varargs in C or C++:

fn(a, b)
fn(a, b, c, d, ...)

This question is related to python

The answer is


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


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)

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

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 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.