Edited by Martin Thomas Humby, Sunday, 26 July 2015, 22:05
Passing an indeterminate number of parameters
Python matches arguments in a call to parameters in the parameter list by position
def func_a(a, b, c): ... val = func_a(d, e, f)
Argument d is matched to a, argument e to b, etc.
Sometimes it is useful to be able to write a function that that accepts any number of arguments. print() is one such function. When this is so prefixing the last parameter in the positional list (perhaps the only parameter) with a * character indicates it is to accept a sequence of one or more arguments:
def func_b(a, b, *args): ... val = func_b(d, e, f, g)
Here d and e are matched to a and b positionally but f and g are wrapped to form a tuple which is passed to args. Tuples can be created on the fly and unpack transparently:
tup = (a, b, c, d) # this creates a tuple tup = 1, 2, 3, 4 # brackets are optional d, e, f, g = tup # the tuple is unpacked
Transparent unpacking cannot be used in the function body when the number of arguments in the tuple is unknown: a mismatch generates an error. Arguments in the tuple are accessed by indexing into it, arg = args[index], or by iterating over it in a for loop
def func_b(a, b, *args): for arg in args: # do something with arg
Another way of providing a function with optional parameters is to use key-word arguments. This kind of argument is doubly useful because inclusion of a particular argument in any call is optional and the argument supplies a default value when not included:
val = func_b(a, b, c, d, i='custard', j=False, k=True)
output: h holds default None custard {'j': False, 'k': True}
The argument h is not included in the call so it is initialized with its default value None. Additionally, including the optional parameter**kwargs prefixed with two stars, allows zero or more additional keyword arguments to be passed to the function. These additional arguments are passed as a dict (dictionary) and access to them is obtained by writing
j = kwargs['j'] # no stars here
for example. If j was not included in the call an error would result so for optional additional key-word arguments we need to write
if 'j' in kwargs: j = kwargs['j'] else: j = 'j default'
Tuple function returns
With one notable exception interpretations of the requirement that a function must only return a single value has been a problem in computing from day one. LISP of course provides the exception. Languages that rely on var parameters or the like to sidestep the single return restriction create an environment where mistakes are all too likely. Such languages feature pass by value conjoined with pass by variable address conjoined with pass by reference.
This is fine in a low level language like C where all is explicit, less so in languages that have pretensions towards a level of abstraction. In any event allowing modification of non-locals at diverse points in a function is not conducive to data integrity when there is some obscure error in the logic or when an exception is thrown.
Python's answer is to supply a single return as a tuple of multiple values that can be unpacked transparently to a list of variables:
def swap(a, b): return b, a # construct a tuple and return it
a, b = 1, 2 print(a, b) a, b = swap(a, b) print(a, b)
output: 1 2 2 1
If the number of variables in the list does not match the returned tuple an error occurs and thus return of a single item of known composition is maintained.
Transparent construction and unpacking of tuples allows multiple assignments, any to any. So, in reality, a swap function is not required to exchange the values at two variables. The construct
a, b = b, a
is all that is needed.
After all the millions of functions that have been written to modify data using side effects it seems unlikely that tuple returns will see much general usage in the near future but in this series I will use this return type whenever it is indicated.
Summary
In Algorithms 3 and 4 we have looked at the usage and structure of functions and the scope of entities within a program including local and other variables. Lazy evaluation and closures will be considered in Algorithms 5.
[Algorithms 4: Indeterminate arguments, complex returns (c) Martin Humby 2015]
Algorithms 4: Indeterminate arguments, complex returns
Passing an indeterminate number of parameters
Python matches arguments in a call to parameters in the parameter list by position
Argument d is matched to a, argument e to b, etc.
Sometimes it is useful to be able to write a function that that accepts any number of arguments. print() is one such function. When this is so prefixing the last parameter in the positional list (perhaps the only parameter) with a * character indicates it is to accept a sequence of one or more arguments:
Here d and e are matched to a and b positionally but f and g are wrapped to form a tuple which is passed to args. Tuples can be created on the fly and unpack transparently:
Transparent unpacking cannot be used in the function body when the number of arguments in the tuple is unknown: a mismatch generates an error. Arguments in the tuple are accessed by indexing into it, arg = args[index], or by iterating over it in a for loop
Another way of providing a function with optional parameters is to use key-word arguments. This kind of argument is doubly useful because inclusion of a particular argument in any call is optional and the argument supplies a default value when not included:
The argument h is not included in the call so it is initialized with its default value None. Additionally, including the optional parameter**kwargs prefixed with two stars, allows zero or more additional keyword arguments to be passed to the function. These additional arguments are passed as a dict (dictionary) and access to them is obtained by writing
for example. If j was not included in the call an error would result so for optional additional key-word arguments we need to write
Tuple function returns
With one notable exception interpretations of the requirement that a function must only return a single value has been a problem in computing from day one. LISP of course provides the exception. Languages that rely on var parameters or the like to sidestep the single return restriction create an environment where mistakes are all too likely. Such languages feature pass by value conjoined with pass by variable address conjoined with pass by reference.
This is fine in a low level language like C where all is explicit, less so in languages that have pretensions towards a level of abstraction. In any event allowing modification of non-locals at diverse points in a function is not conducive to data integrity when there is some obscure error in the logic or when an exception is thrown.
Python's answer is to supply a single return as a tuple of multiple values that can be unpacked transparently to a list of variables:
If the number of variables in the list does not match the returned tuple an error occurs and thus return of a single item of known composition is maintained.
Transparent construction and unpacking of tuples allows multiple assignments, any to any. So, in reality, a swap function is not required to exchange the values at two variables. The construct
is all that is needed.
After all the millions of functions that have been written to modify data using side effects it seems unlikely that tuple returns will see much general usage in the near future but in this series I will use this return type whenever it is indicated.
Summary
In Algorithms 3 and 4 we have looked at the usage and structure of functions and the scope of entities within a program including local and other variables. Lazy evaluation and closures will be considered in Algorithms 5.
[Algorithms 4: Indeterminate arguments, complex returns (c) Martin Humby 2015]