Parameter passing
Parameter passing is somehow standard in Python. For instance:
def fact(n):
if n == 0:
return 1
else:
return n * fact(n-1)
fact(50)
30414093201713378043612608166064768844377641568960512000000000000
Default values
Parameters with default values should end the signature:
def f(a, b=0):
...
def f(a, b=1):
return a+b
f(5)
6
def f(a, b=0, c=1):
return a+b+c
Warning when using mutable default values
Mutable default values can lead to unexpected behavior:
def f(b=[]):
b.append(1)
return b
f()
f()
[1, 1]
The solution is to replace the mutable default argument by an immutable one as follows.
def f(b=None):
if b == None:
b = []
b.append(1)
return b
f()
f()
[1]
Positional VS keyword parameters
A positional parameter is characterized by its position. A keyword parameter is characterized by its name.
f(1, b=4)
f(b=4)
etc.
def f(a, b):
return a-b
f(b=2, a=5)
3
Unpacking arguments
On the calling side, it is possible to unpack tuples/lists and dictionnaries.
Unpacking a tuple/list
For instance,
f(*[1, 2, 3, 4])
is the same as:
f(1, 2, 3, 4)
def f(a, b,c, d):
return a+b+c+d
f(*[1, 2, 3, 4])
10
Warning: it is impossible to use *
elsewhere than in a call.
*[1, 2]
Cell In[8], line 1
*[1, 2]
^
SyntaxError: can't use starred expression here
Unpacking a dictionnary
With **
, you unpack a dictionnary.
f(**{'y': 5, 'z': 6})
is the same as f(y = 5, z= 6)
.
def f(z, y):
print(f"z = {z} and y = {y}")
f(**{'y': 5, 'z': 6})
z = 6 and y = 5
You can use both at the same time:
def f(a, b,c, d, y, z):
return a+b+c+d+y+z
f(*[1, 2, 3, 4], **{'y': 5, 'z': 6})
21
But you cannot give several arguments:
def f(a, b,c, d, y, z):
return a+b+c+d+y+z
f(*[1, 2, 3, 4], **{'a': 42, 'y': 5, 'z': 6})
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[9], line 4
1 def f(a, b,c, d, y, z):
2 return a+b+c+d+y+z
----> 4 f(*[1, 2, 3, 4], **{'a': 42, 'y': 5, 'z': 6})
TypeError: f() got multiple values for argument 'a'
Unpacking in Javascript
In Javascript, unpacking is performed with ...
:
Math.min(...[2, 3, 1])
is the same as Math.min(2, 3, 1)
.
Packing arguments
It is possible to get all (remaining) arguments at once. This is called packing. It is possible to get:
- all (remaining) positional parameters
*args
as the tupleargs
- all (remaining) keyword parameters
**kwargs
as a dictionarykwargs
def f(a, b=0, *args, **kwargs):
return a + b + sum(args) + sum(kwargs.values())
f(1, 2, 3, 4, y=5, z=6)
21
Enforcing parameters to be keyword
A stand-alone *
means that the parameters that follows *
should be given with keywords.
def f(a, b, *, operator):
if operator == "+":
return a+b
else:
return a-b
f(3, 5, '+')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[12], line 7
4 else:
5 return a-b
----> 7 f(3, 5, '+')
TypeError: f() takes 2 positional arguments but 3 were given
def f(a, b, *, operator):
if operator == "+":
return a+b
else:
return a-b
f(3, 5, operator='+')
8
Enforcing parameters to be positional
The /
enforces a
and b
not to be specified by keywords.
def f(a, b, /):
return a+b
f(3, 5)
8
def f(a, b, /):
return a+b
f(a=3, b=5)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[11], line 4
1 def f(a, b, /):
2 return a+b
----> 4 f(a=3, b=5)
TypeError: f() got some positional-only arguments passed as keyword arguments: 'a, b'