• No results found

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 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.

10.7.1 Default Values for Parameters

The most common way to implement optional parameters is by providing a default value for the optional parameters. 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 countparameter. The second form has an explicit argument value of 2 for thecountparameter.

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.

Theint()function does this. We can say ‘int("23")’ to do decimal conversion and ‘int("23",16)’ to do

hexadecimal conversion. Clearly, the second argument toint()has a default value of 10. Important: Red Alert

It’s very, very important to note that default values must be immutable objects. We’ll return to this concept of mutability inData Structures.

For now, be aware that numbers, strings,None, andtupleobjects are immutable.

As we look at various data type, we’ll find that lists, sets and dictionaries are mutable, and cannot be used as default values for function parameters.

Fancy Defaults. 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. Therange()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 value 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. Pythonmustfind 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 basicTypeError. For example:

badcall.py

#!/usr/bin/env python

def hack(a,b): print a+b hack(3)

When we run this example, we see the following. MacBook-5:Examples slott$ python badcall.py Traceback (most recent call last):

File "badcall.py", line 4, in <module> hack(3)

TypeError: hack() takes exactly 2 arguments (1 given)

10.7.2 Providing Argument Values by Keyword

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 settest1, the keyword form is used. The second call of theaverageDice()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:

1. Supply values for all parameters given by name, irrespective of position.

2. Supply values for all remaining parameters by position; in the event of duplicates, raise a TypeError. 3. 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 inAdvanced Parameter Handling For Functions.

10.7.3 Returning Multiple Values

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 atuple. We’ll wait forTuplesfor complete information ontuples. The following is a quick example of how multiple assignment works with functions that return multiple values.

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-valuedtuple. You’ll recall fromMultiple 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.