Python provides a mechanism for optional parameters. This allows us to create a single function which has several alternative forms. In other languages, like C++ or Java, these are called overloaded functions; they are actually separate function definitions with the same name but different parameter forms. In Python, we can write a single function that accepts several parameter forms.
Python has three mechanisms for dealing with optional parameters and a variable number of parameters. We'll cover the basics of optional parameters in this section. The other mechanisms for dealing with variable numbers of parameters will be deferred until the section called “Advanced Parameter Handling For Functions” because these mechanisms use some more advanced data structures.
Python functions can return multiple values. We'll look at this, also.
One way the we can handle optional parameters is by providing a default value for a parameter. If no argument is supplied for the parameter, the default value is used.
def report( spin, count=1 ):
print spin, count, "times in a row"
This silly function can be used in two ways:
report( n ) report( n, 2 )
The first form provides a default argument of 1 for the
count parameter. The second form has an explicit
argument value of 2 for the count
parameter.
If a parameter has no default value, it is not optional. If a parameter has a default value, it is optional. In order to disambiguate the assignment of arguments to parameters, Python uses a simple rule: all required parameters must be first, all optional parameters must come after the required parameters.
The int function does this. We can say
int("23") to do decimal conversion and
int("23",16) to do hexadecimal conversion. Clearly, the
second argument to int has a default value of
10.
When we look at the Python range function, we
see a more sophisticated version of this.
range (x) is the same as
range (0, x,
1)
range (x,
y) is the same as range
(x, y,
1)
It appears from these examples that the first
parameter is optional. The authors of Python use a pretty slick trick
for this that you can use also. The range function
behaves as though the following function is defined.
def range(x, y=None, z=None):
if y==None:
start, stop, step = 0, x, 1
elif z==None:
start, stop, step = x, y, 1
else:
start, stop, step = x, y, z
Real work is done with start, stop and step
By providing a default of None, the function
can determine whether a value was supplied or not supplied. This allows
for complex default handling within the body of the function.
Conclusion. Python must find a value for all parameters. The basic rule is that the values of parameters are set in the order in which they are declared. Any missing parameters will have their default values assigned. These are called positional parameters, since the position is the rule used for assigning argument values when the function is applied.
If a mandatory parameter (a parameter without a default value) is
missing, this is a basic TypeError. For
example.
When we run this example, we see the following.
$python badcall.pyTraceback (most recent call last): File "badcall.py", line 5, in ? hack(3) TypeError: hack() takes exactly 2 arguments (1 given)$
In addition to supplying argument values by position, Python also permits argument values to be specified by name. Using explicit keywords can make programs much easier to read.
First, we'll define a function with a simple parameter list:
import random
def averageDice( samples=100 ):
"""Return the average of a number of throws of 2 dice."""
s = 0
for i in range(samples):
d1,d2 = random.randrange(6)+1,random.randrange(6)+1
s += d1+d2
return float(s)/float(samples)
Next, we'll show three different kinds of arguments: keyword, positional, and default.
test1 = averageDice( samples=200 ) test2 = averageDice( 300 ) test3 = averageDice()
When the averageDice function is evaluated to
set test1, the keyword form is used. The second call
of the averageDice function uses the positional
form. The final example relies on a default for the parameter.
Conclusion. This gives us a number of variations including positional parameters and keyword parameters, both with and without defaults. Positional parameters work well when there are few parameters and their meaning is obvious. Keyword parameters work best when there are a lot of parameters, especially when there are optional parameters.
Good use of keyword parameters mandates good selection of keywords. Single-letter parameter names or obscure abbreviations do not make keyword parameters helpfully informative.
Here are the rules we've seen so far:
Supply values for all parameters given by name, irrespective of position.
Supply values for all remaining parameters by position; in the
event of duplicates, raise a
TypeError.
Supply defaults for any parameters that have defaults defined;
if any parameters still lack values, raise a
TypeError.
There are still more options available for handling variable numbers of parameters. It's possible for additional positional parameters to be collected into a sequence object. Further, additional keyword parameters can be collected into a dictionary object. We'll get to them when we cover dictionaries in the section called “Advanced Parameter Handling For Functions”.
One common desire among programmers is a feature that allows a
function to return multiple values. Python has some built-in functions
that have this property. For example, divmod
returns the divisor and remainder in division. We could imagine a
function, rollDice that would return two values
showing the faces of two dice.
In Python, it is done by returning a tuple.
We'll wait for Chapter 13, Tuples for complete
information on tuples. The following is a quick
example of how multiple assignment works with functions that return
multiple values.
Example 9.4. rolldice.py
import random
def rollDice():
return ( 1 + random.randrange(6), 1 + random.randrange(6) )
d1,d2=rollDice()
print d1,d2
This shows a function that creates a two-valued
tuple. You'll recall from the section called “Multiple Assignment Statement” that Python is perfectly happy with
multiple expressions on the right side of =, and
multiple destination variables on the left side. This is one reason why
multiple assignment is so handy.