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
callable
s share is that they have a very simple
interface: they can be called. Other callable
s
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"