0% found this document useful (0 votes)
3 views5 pages

Advanced Parameter Handling For Functions

The document discusses advanced parameter handling in Python functions, including the ability to accept unlimited positional and keyword arguments using *args and **kwargs. It provides examples of functions that utilize these features, such as calculating maximum values and handling distance, rate, and time calculations. Additionally, it outlines the creation of a custom print function that mirrors the built-in print statement while allowing for more flexible argument handling.

Uploaded by

zinnay6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views5 pages

Advanced Parameter Handling For Functions

The document discusses advanced parameter handling in Python functions, including the ability to accept unlimited positional and keyword arguments using *args and **kwargs. It provides examples of functions that utilize these features, such as calculating maximum values and handling distance, rate, and time calculations. Additionally, it outlines the creation of a custom print function that mirrors the built-in print statement while allowing for more flexible argument handling.

Uploaded by

zinnay6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 5

Advanced Parameter Handling For Functions

In the section called “More Features” we hinted that Python functions can handle a variable
number of argument values in addition to supporting optional argument values. Earlier, when we
defined a function that had optional parameters, it had a definite number of parameters, but some
(or all) could be omitted because we provided default values for them.

If we provide too many positional parameters to a function, Python raises an exception. Consider
the following example. We defined a function of three positional parameters, and then evaluated
it with more than three argument values.

>>>
def avg(a,b,c):
return (a+b+c)/3.0

>>>
avg(10,11,12)

11.0
>>>
avg(10,11,12,13,14,15,16)

Traceback (most recent call last):


File "<pyshell#16>", line 1, in -toplevel-
avg(10,11,12,13,14,15,16)
TypeError: avg() takes exactly 3 arguments (7 given)

Unlimited Number of Positional Argument Values

Python lets us define a function that handles an unknown and unlimited number of argument
values. Examples of built-in functions with a unlimited number of argument values are max and
min.

Rather than have Python raise an exception, we can request the additional positional argument
values be collected into a tuple. To do this, you provide a final parameter definition of the form
* extras . The * indicates that this parameter variable is the place to capture the extra argument
values. The variable, here called extras , will receive a sequence with all of the extra positional
argument values.

You can only provide one such variable (if you provided two, how could Python decide which of
these two got the extra argument values?) You must provide this variable after the ordinary
positional parameters in the function definition.

Examples of Unlimited Positional Arguments. The following function accepts an unlimited


number of positional arguments; it collects these in a single tuple parameter, args.

def myMax( *args ):


max= arg[0]
for a in args[1:]:
if a > max: max= a
return max

We take the first element of the args tuple as our current guess at the maximum value, max. We
use a for loop that will set the variable a to each of the other arguments. If a is larger than our
current guess, we update the current guess, max. At the end of the loop, the post condition is that
we have visited every element in the list args; the current guess must be the largest value.

Here's another example. In this case we have a fixed parameter in the first position and all the
extra parameters collected into a tuple called vals.

def printf( format, *vals ):


print format % vals

This should look familiar to C programmers. Now we can write the following, which may help
ease the transition from C to Python.

printf( "%s = %d", "some string", 2 )


printf( "%s, %s, %d %d", "thing1", "thing2", 3, 22 )

Unlimited Number of Keyword Argument Values

In addition to collecting extra positional argument values into a single parameter, Python can
also collect extra keyword argument values into a dict. If you want a container of keyword
arguments, you provide a parameter of the form ** extras . Your variable, here called extras ,
will receive a dict with all of the keyword parameters.

The following function accepts any number opf keyword arguments; they are collected into a
single parameter.

def rtd( **args ):


if args.has_key( "rate" ) and args.has_key( "time" ):
args["distance"]= args["rate"]*args["time"]
elif args.has_key( "rate" ) and args.has_key( "distance" ):
args["time"]= args["distance"]/args["rate"]
elif args.has_key( "time" ) and args.has_key( "distance" ):
args["rate"]= args["distance"]/args["time"]
else:
raise Exception("%r does not compute" % ( args, ) )
return args

Here's two examples of using this rtd function.

>>>

print rtd( rate=60, time=.75 )


{'distance': 45.0, 'rate': 60.0, 'time': 0.75}
>>>

print rtd( distance=173, time=2+50/60.0 )

{'distance': 173, 'rate': 61.058823529411761,


'time': 2.8333333333333335}

The keyword arguments are collected into a dict, named args. We check for some combination
of "rate", "time" and "distance" by using the dict method has_key. If the dict of keyword
arguments, args, has the given keyword, has_key returns true. For each combination, we can
solve for the remaining value and update the dict by insert the additional key and value into the
dict.

Using a Container Instead of Individual Arguments

We can also force a sequence to be broken down into individual parameters. We can use a
special version of the * operator when evaluating a function. Here's an example of forcing a 3-
tuple to be assigned to three positional parameters.

>>>
def avg3(a,b,c):
... return (a+b+c)/3.0

>>>
avg3( *(4,5,7) )

5.333333333333333

In this example, we told Python to break down our 3-tuple, and assign each value of the tuple
to a separate parameter variable.

As with the * operator, we can use ** to make a dict become a series of keyword parameters to
a function.

>>> d={ 'a':5, 'b':6, 'c':9 }


>>> avg3( **d )
6.666666666666667

In this example, we told Python to assign each element of the dict, d, to a parameter of our
function.

We can mix and match this with ordinary parameter assignment, also. Here's an example.

>>> avg3( 2, b=3, **{'c':4} )


3.0
Here we've called our function with three argument values. The parameter a will get its value
from a simple positional parameter. The parameter b will get its value from a keyword argument.
The parameter c will get its value from having the dict {'c':4} turned into keyword parameter
assignment.

We'll make more use of this in the section called “Inheritance”.

Creating a print function

The print statement has irregular, complex syntax. Also, because it's a statement, making
blanket changes requires tedious, manual search and replace on the program source. Writing a
print function can make the print statement slightly easier to cope with.

We want to mirror the capabilities of the existing print statement, so we need to accept an
unlimited number of positional parameters, as well as some optional keyword parameters. One
keyword parameter can be used in place of the "chevron" feature to define the output file. The
other keyword parameters can provide formatting information: what character goes between
fields and what character (if any) goes at the end of the line.

We want to have a syntax summary like this.

_print( args , sep= string , end= string , file= file )

Converts the argument values to strings, and writes them to the given file. If no file is
provided, writes to standard output. The sep parameter is the column separator, which is
a space by default. The end parameter is the end-of-line character, which is a \n by
default.

A simple version of our print replacement function would look something like the following.
This example looks forward to using the map function, which we won't look at in detail until the
section called “Sequence Processing Functions: map, filter, reduce and zip”.

Example 15.1. printFunction.py

import sys
def _print( *args, **kw ):
out= kw.get('file',sys.stdout)
linesep= kw.get('end','\n')
colsep= kw.get('sep',' ')
out.write( colsep.join( map(str,args) ) )
out.write( linesep )

Our intent is to have a function that we can use as follows. We want to provide a long sequence
of positional parameters first, followed by some optional keyword parameters.

_print( "Python Version", end="" )


_print( sys.version )
_print( "This is", "Stderr", out=sys.stderr, )
_print( "This is", "Stdout", out=sys.stdout, )

Here are the original print statements that we replaced.

print "Python Version",


print sys.version
print >>sys.stderr, "This is", "Stderr"
prinr >>sys.stdout, "This is", "Stdout"

Note that we can't simply say def _print ( *args, sep=' ', end='\n', file=None ) as
the definition of this function. We can't have the "all extra positional parameters" listed first in
the function definition, even though this is our obvious intent. To achieve the syntax we want,
we have to write a function which collects all positional parameters into one sequence of values,
and all keyword parameters into a separate dictionary.

You might also like