Bizarre behavior with mutable default arguments

Arnaud Delobelle arnodel at
Tue Jan 1 10:32:18 CET 2008

On Jan 1, 5:26 am, NickC <ncogh... at> wrote:
> On Jan 1, 3:22 am, Arnaud Delobelle <arno... at> wrote:
> > On Dec 31, 10:58 am, Odalrick <odalr... at> wrote:
> > > I'm surprised noone has said anything about the why of default
> > > mutables. I think it is becasue it isn't easy to do it an other way.
> > [...]
> > There is an easy enough way: evaluate default values when the function
> > is called rather than when it is defined.  This behaviour comes with
> > its own caveats as well I imagine, and it's not 'as easy' to implement
> > as the current one.
> As Odalrick notes, there is no way to give different calls to a
> function their own copies of mutable default arguments without re-
> evaluating the defaults every time the function is called. The
> horrendous performance implications mean that that simply isn't going
> to happen. So the status quo, where the defaults are calculated once
> when the function is defined and the result cached in the function
> object is unlikely to change.

I'm in no way advocating a change, in fact I wouldn't like things to
change.  I was just saying that it was not difficult (technically) to
alter the behaviour, but that this change wouldn't be desirable
because it would make code more difficult to reason on.  OTOH a very
common idiom in python is

def foo(x, y, z=None):
    if z is None: z = ['a', 'mutable', 'object']
    # stuff that foo does

This the current way to say "I want the default value of z to be
reevaluated each time it is used".  I use this much more often than

def bar(x, y, z=ExpensiveImmutableCreation())

So I'm not so convinced with the performance argument at face value
(though it's probably pertinent:)

> > What's good about the current behaviour is that it is easy to reason
> > with (once you know what happens), even though you almost have to get
> > bitten once.  But using this to have static variable is extremely ugly
> > IMHO.
> The only thing it doesn't give you is a static variable that isn't
> visible to the caller. Py3k's keyword-only arguments (PEP 3102) will
> make those cases a little tidier, since it won't be possible to
> accidentally replace the static variables by providing too many
> positional arguments.

I was always a bit puzzled by this PEP.  If this is one of the
underlying reasons for it, then I am even more puzzled.

> I believe the suggestion of permitting static variables after the **
> entry in a function's parameter list was raised during the PEP 3102
> discussions, but never gained much traction over a '_cache={}' keyword-
> only argument approach (and the latter has the distinct advantage of
> being *much* easier to test, since you can override the cache from the
> test code to ensure it is being handled correctly).

Well I'm glad that didn't go through, argument lists in function
definitions are complicated enough already!


More information about the Python-list mailing list