initializing with empty list as default causes freaky problems

Benjamin Kaplan benjamin.kaplan at case.edu
Mon Jul 27 15:30:31 EDT 2009


On Mon, Jul 27, 2009 at 1:40 PM, Reckoner<reckoner at gmail.com> wrote:
> Hi,
>
> Observe the following:
>
> In [202]: class Foo():
>   .....:     def __init__(self,h=[]):
>   .....:         self.h=h
>   .....:
>   .....:
>
> In [203]: f=Foo()
>
> In [204]: g=Foo()
>
> In [205]: g.h
> Out[205]: []
>
> In [206]: f.h
> Out[206]: []
>
> In [207]: f.h.append(10)
>
> In [208]: f.h
> Out[208]: [10]
>
> In [209]: g.h
> Out[209]: [10]
>
> The question is: why is g.h updated when I append to f.h?  Shouldn't
> g.h stay []?
>
> What am I missing here?
>
> I'm using Python 2.5.1.
>
> Thanks in advance.


. It has to do with the way Python handles functions and class
methods. Basically, when the parser creates the class Foo, it also
creates all of Foo's class variables and functions. It's at this
point, and only at this point, that the default parameter is
evaluated.

When you make an instance of Foo, just wraps the function __init__ by
filling in the initial parameter. Because both f and g are really
using the Foo.__init__ function (as opposed to separate f.__init__ and
g.__init__ methods), they share the same default parameter, a list
that was created at the very beginning.

Since f.h and g.h both refer to the same list, updating f.h will also
update g.h (and the default parameter). That's why it's a bad idea to
use mutable default parameters- use either None

class Foo(object) :
   def __init__(self, h=None) :
      if h is None:
         h = []

or, if None is an acceptable value, make a sentinel value

sentinel = object()
class Foo(object) :
   def __init__(self, h = sentinel) :
      if h is sentinel:
         h = []
> --
> http://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list