The *args and **kwargs is a common idiom to allow arbitrary number of arguments to functions as described in the section more on defining functions in the Python documentation.

*args

The *args will give you all function parameters as a tuple. You would use *args when you’re not sure how many arguments might be passed to your function.

tmp_list = [1, 2, 3]
tmp_tuple = (4, 5, 6)
tmp_dict = {'m': 7, 'v': 8, 'p': 49}

def test_args(*args):
    print args

test_args() # ()
test_args(0) #(0,)
test_args(*tmp_list) # (1, 2, 3)
test_args(*tmp_tuple) # (4, 5, 6)
test_args(*tmp_dict) # ('p', 'm', 'v')

**kwargs

The **kwargs will give you all keyword arguments except for those corresponding to a formal parameter as a dictionary. **kwargs allows you to handle named arguments that you have not defined in advance.

def test_kwargs(**kwargs):
    for k in kwargs:
        print k, kwargs[k]

'''
age 20
name kwargs
'''
test_kwargs(name='kwargs', age=20)

Mixup

You can also use both in the same function definition but *args must occur before **kwargs.

tmp_list = [1, 2, 3]
tmp_tuple = (4, 5, 6)
tmp_dict = {'m': 7, 'v': 8, 'p': 49}

def test_mixup(*args, **kwargs):
    if args:  
        print 'args:', args

    if kwargs: 
        print 'kwargs:', kwargs

test_mixup(tmp_list) # args: ([1, 2, 3],)
test_mixup(tmp_list, tmp_tuple) # args: ([1, 2, 3], (4, 5, 6))
test_mixup(tmp_list, tmp_dict) # args: ([1, 2, 3], {'p': 49, 'm': 7, 'v': 8})

test_mixup(tmp_tuple, lis=tmp_list, dic=tmp_dict) # kwargs: {'dic': {'p': 49, 'm': 7, 'v': 8}, 'lis': [1, 2, 3]}

Summary

Now let us study the * operator and ** operator. Please note these operators can be used in 2 areas:

  1. function call
  2. function definition

The previous section described * and ** used in function definition:

  • In function definition, the * operator packs the received arguments into a tuple.
  • In function definition, the ** operator packs the received arguments into a dictionary.

Vice verse, these operators in function call can unpack arguments.

  • * operator unpacks data structure such as a list or tuple into arguments needed by function definition.
  • ** operator unpacks a dictionary into arguments needed by function definition.
def test_unpack(arg1, arg2, arg3):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", arg3)

'''
('arg1:', 'two')
('arg2:', 3)
('arg3:', 5)
'''
args = ('two', 3, 5)
test_unpack(*args)

'''
('arg1:', 5)
('arg2:', 'two')
('arg3:', 3)
'''
kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
test_unpack(**kwargs)

tmp_list = [1, 2, 3]
tmp_tuple = (4, 5, 6)
tmp_dict = {'m': 7, 'v': 8, 'p': 49}

'''
('arg1:', 1)
('arg2:', 2)
('arg3:', 3)
'''
test_unpack(*tmp_list)

'''
('arg1:', 4)
('arg2:', 5)
('arg3:', 6)
'''
test_unpack(*tmp_tuple)

'''
Traceback (most recent call last):
  File "code.py", line 30, in <module>
    test_unpack(**tmp_tuple)
TypeError: test_unpack() argument after ** must be a mapping, not tuple
'''
test_unpack(**tmp_tuple)

'''
('arg1:', 'p')
('arg2:', 'm')
('arg3:', 'v')
'''
test_unpack(*tmp_dict)

'''
Traceback (most recent call last):
  File "code.py", line 31, in <module>
    test_unpack(**tmp_dict)
TypeError: test_unpack() got an unexpected keyword argument 'p'
'''
test_unpack(**tmp_dict)

Reference