One interesting consequence of the Python world-view is that a
function is an object of the class function, a
subclass of callable. The common feature that all
callables share is that they have a very simple
interface: they can be called. Other callables
include the built-in functions, generator functions (which have the
yield
statement instead of the
return
statement) and things called lambdas.
Sometimes we don't want to call and evaluate a function. Sometimes
we want to do other things to or with a function. For example, the various
factory functions (int, long,
float, complex) can be used with
the isinstance function instead of being called to
create a new object.
For example, isinstance(2,int) has a value of
True. It uses the int function,
but doesn't apply the int function.
A function object is created with the
def
statement. Primarily, we want to evaluate the function objects we create.
However, because a function is an object, it has attributes, and it can be
manipulated to a limited extent.
From a syntax point of view, a name followed by ()'s is
a function call. You can think of the ()'s as the "call"
operator: they require evaluation of the arguments, then they apply the
function.
name
(
arguments
)
When we use a function name without ()'s, we are
talking about the function object. There are a
number of manipulations that you might want to do with a function
object.
Call The Function. By far, the most common use for a function object is to call it.
When we follow a function name with ()'s, we are calling
the function: evaluating the arguments, and applying the function.
Calling the function is the most common manipulation.
Alias The Function. This is dangerous, because it can make a program obscure. However,
it can also simplify the evoluation and enhancement of software. Imagine
that the first version of our program had two functions named
rollDie and rollDice. The
definitions might look like the following.
def rollDie():
return random.randrange(1,7)
def rollDice():
return random.randrange(1,7) + random.randrange(1,7)
When we wanted to expand our program to handle five-dice games, we
realized we could generalize this function.
def rollNDice( n=2 ):
t= 0
for d in range(n):
t += random.randrange( 1, 7 )
return t
It is important to remove the duplicated algorithm in all three
versions of our dice rolling function. Since rollDie
and rollDice are just special cases of
rollNDice, we should replace them with something like
the following.
def rollDie():
return rollNDice( 1 )
def rollDice():
return rollNDice()
This revised definition of rollDice is really
just an another name for the ollNDice. Because a
function is an object assigned to a variable, we can have multiple
variables assigned to the function. Here's how we create an alias to a
function.
rollDice = rollNDice
Warning
Function alias definitions helps maintaining compatibility between
old and new releases of software. It is not something that should be
done as a general practice; we need to be careful providing multiple
names for a given function. This can be a simplification. It can also be
a big performance improvement for certain types of functions that are
heavily used deep within nested loops.
Function Attributes. A function object has a number of attributes. We can interrogate
those attributes, and to a limited extend, we can change some of these
attributes. For more information, see section 3.2 of the
Python Language Reference and section 2.3.9.3 of
the Python Library Reference.
-
func_doc,
__doc__
-
Docstring from the first line of the function's body.
-
func_name,
__name__
-
Function name from the
def
statement.
-
__module__
-
Name of the module in which the function name was
defined.
-
func_defaults
-
Tuple with default values to be assigned to each argument that
has a default value. This is a subset of the parameters, starting
with the first parameter that has a default value.
-
func_code
-
The actual code object that is the suite of statements in the
body of this function.
-
func_globals
-
The dictionary that defines the global namespace for the
module that defines this function. This is
m.__dict__ of the module which defined this
function.
-
func_dict,
__dict__
-
The dictionary that defines the local namespace for the
attributes of this function.
You can set and get your own function attributes, also.
def rollDie():
return random.randrange(1,7)
rollDie.version= "1.0"
rollDie.authoor= "sfl"