Pre-PEP: Dynamically evaluating default function arguments

Daniel Ehrenberg LittleDanEhren at yahoo.com
Tue Jan 6 23:52:21 CET 2004


One of the most common bugs that people have on the Python Tutor list
are caused by the fact the default arguments for functions are
evaluated only once, not when the function is called. The solution to
this is usually to use the following idiom:

def write_stuff(stuff=None):
    """Function to write its argument.

Defaults to whatever is in the variable "things"
"""
    if stuff is None:
        stuff = things
    print stuff

However, it would be much more intuitive and concise if the following
could be done instead, but with the guarantee that changes in the
variable 'things' will be noticed:

def write_stuff(stuff=things):
    print stuff

This would instead print whatever is in things when the function is
defined.

The goal of this pre-PEP is to make it so that the default arguments
are evaluated dynamically instead of when the function is created. As
this is a pre-PEP, the details have not been finalized yet. One of the
first details is whether or not the default argument should be checked
to make sure it exists before the function is called. I think it would
make the most sense if things were evaluated when the function was
defined but the result was not saved and was reevaluated whenever the
function is called. This might not be the best way to do it, though,
and it might be better to treat it just like a regular equals sign.

As with any additional dynamic properties added, there is the
possibility of some errors to go uncaught and some. Here is an example
of some hypothetical (but unlikely) code that would cause an error as
a result of this change:

>>> x = 5
>>> def return_something(stuff=x):
        return stuff
>>> return_something()
5
>>> x += 1
>>> return_something() #dynamic now
6
>>> del x
>>> return_something()
Traceback (most recent call last):
  File "<input>", line 1, in ?
NameError: name 'x' is not defined

To me, this seems like the logical behavior, but there is still the
possiblility of some programs being broken. A way to preserve
backwards compatability could be to store the initial evaluation of
the default and use it to fall back on if the variable needed isn't
around anymore, but this seems overly complicated.

Daniel Ehrenberg



More information about the Python-list mailing list