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
Link to heading
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
Link to heading
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 Link to heading
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 Link to heading
Now let us study the * operator and ** operator. Please note these operators can be used in 2 areas:
- function call
- 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