Python - Understanding args, kwargs in functions

Logo

Introduction

As a beginner in Python language, you encounter sample codes with the following syntaxes :

def log_error(self, msg, *args, **kwargs)
  • If you are used to Javascript, PHP…, you wonder : *args, **kwargs, what’s that ?
  • If you are used to C or Go languages, you wonder : *args, **kwargs, pointers in Python ?

*args and **kwargs allow you to pass multiple arguments and keyword arguments to a function. Let’s explain *args and **kwargs through basic examples.

A simple function returning a sum, args

argkarg.py
def sum(x,y):
	return x + y

print(sum(1,2))
$ python3 argkarg.py
3

This function works well if there is only 2 integer arguments. *args is used to specify several arguments :

argkarg.py
def sum(*args):
	r = 0
	for x in args:
		r += x
	
	return r

print(sum(10,20,30,40))
100

args is just a name, another name can be used :

def sum(*listint):
	r = 0
	for x in listint:
    …

The unpacking operator * is important here. args in the function is then a tuple object, not a list object. Tuple objects are immutable, values cannot be changed after assignment.

def sum(*args):

  print(args)
  print(type(args))

  r = 0
  for x in args:
		r += x
	
  return r

print(sum(10,20,30,40))
(10, 20, 30, 40)
<class 'tuple'>
100

Use also the unpacking operator * if arguments values are stored in list or tuple objects :

l = [10,20,30,40]
print(sum(*l))

t = [100,200,300,400]
print(sum(*t))
100
1000

kwargs in functions

**kwargs works like *args but for named arguments (kw for keyword).

def sum(**kwargs):
	r = 0
	for x in kwargs.values():
		r += x
	
	return r

print(sum(a=10,b=20,c=30,d=40))
100

Like args, kwargs is just a name and can be changed.

The unpacking operator ** leads to a dictionary, mutable. kwargs is a dictionary :

def sum(**kwargs):
	print(kwargs)
	print(type(kwargs))

	r = 0
	for x in kwargs.values():
		r += x
	
	return r

print(sum(a=10,b=20,c=30,d=40))
<class 'dict'>
{'a': 10, 'b': 20, 'c': 30, 'd': 40}
100

Combining args and kwargs, arguments order

Arguments order is important in the function declaration when *args and **kwargs are both used :

  1. Regular arguments
  2. *args arguments
  3. **kwargs arguments
def sum(x,y,*args,**kwargs):
	
	r=0
	r = x + y

	for i in args:
		r += i
	
	for i in kwargs.values():
		r += i
	
	return r

print(sum(1,2,3,4,a=10,b=20,c=30,d=40))110

Invalid syntax error is raised when the order is not the right one :

def sum(x,y,**kwargs,*args):
  …
  File "argkarg.py", line 15
    def sum(x,y,**kwargs,*args):
                          ^
SyntaxError: invalid syntax

The unpacking operators * and **

The operator * unpack iterables : lists, tuples

l = [1,2,3]
print(*l)

t = (1,2,3)
print(*t)
1 2 3
1 2 3

This operator * is useful to merge lists and/or tuples, an example :

t1 = (1,2,3)
t2 = (4,5)
l1 = [6,7]

t3 = (*t1,*t2,*l1)
l2 = [*t1,*t2,*l1]
print(t3)
print(l2)
(1, 2, 3, 4, 5, 6, 7)
[1, 2, 3, 4, 5, 6, 7]

The operator ** unpack dictionaries, useful to merge dictionaries :

d1 = { 'a' : 10, 'b' : 20 }
d2 = { 'c' : 30, 'd' : 40 }
d3 = { **d1, **d2 }

print(d3)
{'a': 10, 'b': 20, 'c': 30, 'd': 40}