Section 11.5. Formal Arguments


11.5. Formal Arguments

A Python function's set of formal arguments consists of all parameters passed to the function on invocation for which there is an exact correspondence to those of the argument list in the function declaration. These arguments include all required arguments (passed to the function in correct positional order), keyword arguments (passed in or out of order, but which have keywords present to match their values to their proper positions in the argument list), and all arguments that have default values that may or may not be part of the function call. For all of these cases, a name is created for that value in the (newly created) local namespace and it can be accessed as soon as the function begins execution.

11.5.1. Positional Arguments

These are the standard vanilla parameters that we are all familiar with. Positional arguments must be passed in the exact order in which they are defined for the functions that are called. Also, without the presence of any default arguments (see next section), the exact number of arguments passed to a function (call) must be exactly the number declared:

>>> def foo(who):     # defined for only 1 argument ...  print 'Hello', who ... >>> foo()              # 0 arguments... BAD Traceback (innermost last):   File "<stdin>", line 1, in ? TypeError: not enough arguments; expected 1, got 0 >>> >>> foo('World!')      # 1 argument... WORKS Hello World! >>> >>> foo('Mr.', 'World!')# 2 arguments... BAD Traceback (innermost last):   File "<stdin>", line 1, in ? TypeError: too many arguments; expected 1, got 2


The foo() function has one positional argument. That means that any call to foo() must have exactly one argument, no more, no less. You will become extremely familiar with TypeError otherwise. Note how informative the Python errors are. As a general rule, all positional arguments for a function must be provided whenever you call it. They may be passed into the function call in position or out of position, granted that a keyword argument is provided to match it to its proper position in the argument list (review Section 11.2.2). Default arguments, however, do not have to be provided because of their nature.

11.5.2. Default Arguments

Default arguments are parameters that are defined to have a default value if one is not provided in the function call for that argument. Such definitions are given in the function declaration header line. C++ supports default arguments too and has the same syntax as Python: the argument name is followed by an "assignment" of its default value. This assignment is merely a syntactical way of indicating that this assignment will occur if no value is passed in for that argument.

The syntax for declaring variables with default values in Python is such that all positional arguments must come before any default arguments:

def func(posargs, defarg1=dval1, defarg2=dval2,...):     "function_documentation_string"     function_body_suite


Each default argument is followed by an assignment statement of its default value. If no value is given during a function call, then this assignment is realized.

Why Default Arguments?

Default arguments add a wonderful level of robustness to applications because they allow for some flexibility that is not offered by the standard positional parameters. That gift comes in the form of simplicity for the applications programmer. Life is not as complicated when there are a fewer number of parameters that one needs to worry about. This is especially helpful when one is new to an API interface and does not have enough knowledge to provide more targeted values as arguments.

The concept of using default arguments is analogous to the process of installing software on your computer. How often does one choose the "default install" over the "custom install?" I would say probably almost always. It is a matter of convenience and know-how, not to mention a time-saver. And if you are one of those gurus who always chooses the custom install, please keep in mind that you are one of the minority.

Another advantage goes to the developers, who are given more control over the software they create for their consumers. When providing default values, they can selectively choose the "best" default value possible, thereby hoping to give the user some freedom of not having to make that choice. Over time, as the users becomes more familiar with the system or API, they may eventually be able to provide their own parameter values, no longer requiring the use of "training wheels."

Here is one example where a default argument comes in handy and has some usefulness in the growing electronic commerce industry:

>>> def taxMe(cost, rate=0.0825): ...     return cost + (cost * rate) ... >>> taxMe(100) 108.25 >>> >>> taxMe(100, 0.05) 105.0


In the example above, the taxMe() function takes the cost of an item and produces a total sale amount with sales tax added. The cost is a required parameter while the tax rate is a default argument (in our example, 8.25%). Perhaps you are an online retail merchant, with most of your customers coming from the same state or county as your business. Consumers from locations with different tax rates would like to see their purchase totals with their corresponding sales tax rates. To override the default, all you have to do is provide your argument value, such as the case with taxMe(100, 0.05) in the above example. By specifying a rate of 5%, you provided an argument as the rate parameter, thereby overriding or bypassing its default value of 0.0825.

All required parameters must be placed before any default arguments. Why? Simply because they are mandatory, whereas default arguments are not. Syntactically, it would be impossible for the interpreter to decide which values match which arguments if mixed modes were allowed. A SyntaxError is raised if the arguments are not given in the correct order:

>>> def taxMe2(rate=0.0825, cost): ...     return cost * (1.0 + rate) ... SyntaxError: non-default argument follows default argument


Let us take a look at keyword arguments again, using our old friend net_conn().

def net_conn(host, port):     net_conn_suite


As you will recall, this is where you can provide your arguments out of order (positionally) if you name the arguments. With the above declarations, we can make the following (regular) positional or keyword argument calls:

  • net_conn('kappa', 8000)

  • net_conn(port=8080, host='chino')

However, if we bring default arguments into the equation, things change, although the above calls are still valid. Let us modify the declaration of net_conn() such that the port parameter has a default value of 80 and add another argument named stype (for server type) with a default value of 'tcp':

def net_conn(host, port=80, stype='tcp'):     net_conn_suite


We have just expanded the number of ways we can call net_conn(). The following are all valid calls to net_conn():

• net_conn('phaze', 8000, 'udp')     # no def args used • net_conn('kappa')                  # both def args used • net_conn('chino', stype='icmp')    # use port def arg • net_conn(stype='udp', host='solo') # use port def arg • net_conn('deli', 8080)             # use stype def arg • net_conn(port=81, host='chino')    # use stype def arg


What is the one constant we see in all of the above examples? The sole required parameter, host. There is no default value for host, thus it is expected in all calls to net_conn().

Keyword arguments prove useful for providing for out-of-order positional arguments, but, coupled with default arguments, they can also be used to "skip over" missing arguments as well, as evidenced from our examples above.

Default Function Object Argument Example

We will now present yet another example of where a default argument may prove beneficial. The grabWeb.py script, given in Example 11.4, is a simple script whose main purpose is to grab a Web page from the Internet and temporarily store it to a local file for analysis. This type of application can be used to test the integrity of a Web site's pages or to monitor the load on a server (by measuring connectability or download speed). The process() function can be anything we want, presenting an infinite number of uses. The one we chose for this exercise displays the first and last non-blank lines of the retrieved Web page. Although this particular example may not prove too useful in the real world, you can imagine what kinds of applications you can build on top of this code.

Example 11.4. Grabbing Web Pages (grabWeb.py)

This script downloads a Web page (defaults to local www server) and displays the first and last non-blank lines of the HTML file. Flexibility is added due to both default arguments of the download() function, which will allow overriding with different URLs or specification of a different processing function.

1 #!/usr/bin/env python 2 3 from urllib import urlretrieve 4 5 def firstNonBlank(lines): 6     for eachLine in lines: 7         if not eachLine.strip(): 8             continue 9         else: 10            return eachLine 11 12 def firstLast(webpage): 13   f = open(webpage) 14   lines = f.readlines() 15   f.close() 16   print firstNonBlank(lines), 17   lines.reverse() 18   print firstNonBlank(lines), 19 20 def download(url='http://www', 21         process=firstLast): 22     try: 23         retval = urlretrieve(url)[0] 24     except IOError: 25         retval = None 26     if retval:          # do some processing 27         process(retval) 28 29 if __name__ == '__main__': 30 download()

Running this script in our environment gives the following output, although your mileage will definitely vary since you will be viewing a completely different Web page altogether.

$ grabWeb.py <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> </HTML>




Core Python Programming
Core Python Programming (2nd Edition)
ISBN: 0132269937
EAN: 2147483647
Year: 2004
Pages: 334
Authors: Wesley J Chun

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net