A parameter falls in one of the following five categories
Positional or keyword
The default category
Positional only
Parameters that are defined on the left side of the slash parameter (/)
Keyword only
Parameters that are defined on the right side of the asterisk parameter (*)
Var positional
At most one that is defined with a asterisk (*paramName)
Var keyword
At most one that is defined with two asterisks (**paramName)
Keyword arguments are named.
when calling a function, the names of the keyword arguments are separated from the argument values by an equal sign (=):
F(param_one = 42, param_two = 'hello World')
Positional arguments are not named.
When calling a function, the values of positional arguments are just stated by themselves, separated by a comma. (Hence, they're positional):
F(42, 'hello World')
Positional arguments must precede keyword arguments.
Positional arguments can also be passed from an iterable by prepending it with a * which expands the elements of the iterable to the passed parameters:
F(*iterable)
Keyword arguements can also be passed from a dict whose key-names correspond to the parameter-names. The dictionary is prepended by two asterisks (**):
F(**vals)
Passing (mutable) objects
The following example tries to demonstrate that objects are passed by reference.
Although an object is passed by reference, it is not possible to return a different object by the parameter. However, if the passed argument is a mutable object, the contents of the object can be modifed so that the caller sees the modifications.
def F(p):
#
# p refers to the same object that was passed
# when F was called:
#
print('id(p) = {}'.format(id(p)))
# Create a new object and let p refer
# to the new object. This has no effect
# on the reference that was passed to F:
#
p=[11,22,33]
#
# Another id will be printed:
#
print('id(p) = {}'.format(id(p)))
# -------------------------------------
def G(q):
print('id(q) = {}'.format(id(q)))
#
# No new object is created, thus
# the caller will see the changed
# values:
#
q[0] = 11
q[1] = 22
q[2] = 33
#
# Same id is printed as before:
#
print('id(q) = {}'.format(id(q)))
# -------------------------------------
V = [1, 2, 3]
print('id(V) = {}'.format(id(V)))
F(V)
for v in V:
print(v) # prints 1, 2 and 3
G(V)
for v in V:
print(v) # prints 11, 22, 33
Function parameters can be given default argument values. The values are used if the parameters are not explicitly given a value when the function is called:
def F(par, num = 42, txt='Hello world'):
print('par = {}'.format(par))
print('num = {}'.format(num))
print('txt = {}'.format(txt))
print('')
F('foo')
#
# par = foo
# num = 42
# txt = Hello world
F('bar', 99)
#
# par = bar
# num = 99
# txt = Hello world
F('baz', 3, 'good bye')
#
# par = baz
# num = 3
# txt = good bye
F('baz', txt='abcdef')
#
# par = baz
# num = 42
# txt = abcdef
A variable number of positional arguments («variadic arguments») is indicated by *posArgs. In this case, posArgs is a tuple that contains the respective values.
A variable number of named arguments is indicated by **namedArgs. In this case, namedArgs is a dict that contains the respective parameter/argument pairs.
def F(par_1, par_2, *posArgs, **namedArgs):
print('par_1 : ', par_1)
print('par_2 : ', par_2)
for posArg in posArgs:
print('posArg: ', posArg)
for parName, argVal in namedArgs.items():
print('{:6s}: {}'.format(parName, argVal))
print('')
F( 42, 'hello World')
F( 99, 'ninety-nine', 'foo', 'bar', 'baz')
F('A', 'B' , x = 'eggs', y = 'why')
F('C', 'D' , 'E', 'F', ltr = 'G')