DekGenius.com
[ Team LiB ] Previous Section Next Section

12.2 Coding Functions

Although it wasn't made very formal, we've already been using functions in earlier chapters. For instance, to make a file object, we call the built-in open function. Similarly, we use the len built-in function to ask for the number of items in a collection object.

In this chapter, we will learn how to write new functions in Python. Functions we write behave the same way as the built-ins already seen: they are called in expressions, are passed values, and return results. But writing new functions requires a few additional ideas that haven't yet been applied. Moreover, functions behave very differently in Python than they do in compiled languages like C. Here is a brief introduction to the main concepts behind Python functions, which we will study in this chapter:

  • def is executable code. Python functions are written with a new statement, the def. Unlike functions in compiled languages such as C, def is an executable statement—your function does not exist until Python reaches and runs the def. In fact, it's legal (and even occasionally useful) to nest def statements inside if, loops, and even other defs. In typical operation, def statements are coded in module files, and are naturally run to generate functions when the module file is first imported.

  • def creates an object and assigns it to a name. When Python reaches and runs a def statement, it generates a new function object and assigns it to the function's name. As with all assignments, the function name becomes a reference to the function object. There's nothing magic about the name of a function—as we'll see, the function object can be assigned to other names, stored in a list, and so on. Functions may also be created with the lambda expression—a more advanced concept deferred until later in this chapter.

  • return sends a result object back to the caller. When a function is called, the caller stops until the function finishes its work and returns control to the caller. Functions that compute a value send it back to the caller with a return statement; the returned value becomes the result of the function call. Functions known as generators may also use the yield statement to send a value back and suspend their state, such that they may be resumed later; this is also an advanced topic covered later in this chapter.

  • Arguments are passed by assignment (object reference). In Python, arguments are passed to functions by assignment (which, as we've learned, means object reference). As we'll see, this isn't quite like C's passing rules or C++'s reference parameters—the caller and function share objects by references, but there is no name aliasing. Changing an argument name does not also change a name in the caller, but changing passed-in mutable objects can change objects shared by the caller.

  • global declares module-level variables that are to be assigned. By default, all names assigned in a function are local to that function and exist only while the function runs. To assign a name in the enclosing module, functions need to list it in a global statement. More generally, names are always looked up in scopes—places where variables are stored—and assignments bind names to scopes.

  • Arguments, return values, and variables are not declared. As with everything in Python, there are no type constraints on functions. In fact, nothing about a function needs to be declared ahead of time: we can pass in arguments of any type, return any kind of object, and so on. As one consequence, a single function can often be applied to a variety of object types.

If some of the preceding words didn't sink in, don't worry—we'll explore all these concepts with real code in this chapter. Let's get started by expanding on these ideas, and looking at a few first examples along the way.

12.2.1 def Statements

The def statement creates a function object and assigns it to a name. Its general format is as follows:

def <name>(arg1, arg2,... argN):
    <statements>

As with all compound Python statements, def consists of a header line, followed by a block of statements, usually indented (or a simple statement after the colon). The statement block becomes the function's body—the code Python executes each time the function is called. The header line specifies a function name that is assigned the function object, along with a list of zero or more arguments (sometimes called parameters) in parenthesis. The argument names in the header will be assigned to the objects passed in parentheses at the point of call.

Function bodies often contain a return statement:

def <name>(arg1, arg2,... argN):
    ...
    return <value>

The Python return statement can show up anywhere in a function body; it ends the function call and sends a result back to the caller. It consists of an object expression that gives the function's result. The return is optional; if it's not present, a function exits when control flow falls off the end of the function body. Technically, a function without a return returns the None object automatically, but it is usually ignored.

12.2.2 def Executes at Runtime

The Python def is a true executable statement: when it runs, it creates and assigns a new function object to a name. Because it's a statement, it can appear anywhere a statement can—even nested in other statements. For instance, it's completely legal to nest a function def inside an if statement, to select between alternative definitions:

if test:
    def func(  ):          # Define func this way.
        ... 
else:
    def func(  ):          # Or else this way instead.
        ...
...
func(  )                   # Call the version selected and built.

One way to understand this code is to realize that the def is much like an = statement: it simply assigns a name at runtime. Unlike compiled languages like C, Python functions do not need to be fully defined before the program runs. More generally, defs are not evaluated until reached and run, and code inside defs is not evaluated until the function is later called.

Because function definition happens at runtime, there's nothing special about the function name, only the object it refers to:

othername = func           # Assign function object.
othername(  )              # Call func again.

Here, the function was assigned to a different name, and called through the new name. Like everything else in Python, functions are just objects; they are recorded explicitly in memory at program execution time.

    [ Team LiB ] Previous Section Next Section