DekGenius.com
[ Team LiB ] Previous Section Next Section

12.3 A First Example: Definitions and Calls

Apart from such runtime concepts (which tend to seem most unique to programmers with backgrounds in traditional compiled languages), Python functions are straightforward to use. Let's code a first real example to demonstrate the basics. Really, there are two sides to the function picture: a definition—the def that creates a function, and a call—an expression that tells Python to run the function's body.

12.3.1 Definition

Here's a definition typed interactively that defines a function called times, which returns the product of its two arguments:

>>> def times(x, y):      # Create and assign function.
...     return x * y      # Body executed when called.
...

When Python reaches and runs this def, it creates a new function object that packages the function's code, and assign the object to the name times. Typically, this statement is coded in a module file, and it would run when the enclosing file is imported; for something this small, though, the interactive prompt suffices.

12.3.2 Calls

After the def has run, the program can call (run) the function by adding parentheses after the function's name; the parentheses may optionally contain one or more object arguments, to be passed (assigned) to the names in the function's header:

>>> times(2, 4)           # Arguments in parentheses
8

This expression passes two arguments to times: the name x in the function header is assigned the value 2, y is assigned 4, and the function's body is run. In this case, the body is just a return statement, which sends back the result as the value of the call expression. The returned object is printed here interactively (as in most languages, 2*4 is 8 in Python); it could also be assigned to a variable if we need to use it later:

>>> x = times(3.14, 4)    # Save the result object.
>>> x
12.56

Now, watch what happens when the function is called a third time, with very different kinds of objects passed in:

>>> times('Ni', 4)        # Functions are "typeless."
'NiNiNiNi'

In this third call, a string and an integer are passed to x and y, instead of two numbers. Recall that * works on both numbers and sequences; because you never declare the types of variables, arguments, or return values, you can use times to multiply numbers or repeat sequences.

12.3.3 Polymorphism in Python

In fact, the very meaning of the expression x * y in the simple times function depends completely upon the kinds of objects that x and y are—it means multiplication first and repetition second. Python leaves it up to the objects to do something reasonable for this syntax.

This sort of type-dependent behavior is known as polymorphism—which means that the meaning of operations depends on the objects being operated upon. Because Python is a dynamically typed language, polymorphism runs rampant: every operation is a polymorphic operation in Python.

This is a deliberate thing, and accounts for much of the language's flexibility. A single function, for instance, can generally be applied to a whole categoy of object types. As long as those objects support the expected interface (a.k.a. protocol), they can be processed by the function. That is, if the objects passed in to a function have the expected methods and operators, they are plug-and-play compatible with the function's logic.

Even in our simple times function, this means that any two objects that support a * will work, no matter what they may be, and no matter when they may be coded. Moreover, if the objects passed in do not support this expected interface, Python will detect the error when the * expression is run, and raise an exception automatically. It's pointless to code error checking ourselves here.

This turns out to be a crucial philosophical difference between Python and statically typed languages like C++ and Java: in Python, your code is not supposed to care about specific data types. If it does, it will be limited to work on just the types you anticipated when you wrote your code. It will not support other compatible object types coded in the future. Although it is possible to test for types with tools like the type built-in function, doing so breaks your code's flexibility. By and large, we code to object interfaces in Python, not data types.

    [ Team LiB ] Previous Section Next Section