0

Why doesn't Python use the default argument values when initializing a superclass?

class Base:
    def __init__(self, list=[]):
        self.list = list

class Sub(Base):
    def __init__(self, item):
        Base.__init__(self)
        self.list.append(item)

x = Sub(1)
y = Sub(2)

print x.list   # prints [1, 2]
print y.list   # prints [1, 2]

In this case, it seems that there is only one 'list' variable that's shared between the two instances of Sub. I can solve the issue by explicitly passing the value of 'list', i.e.:

class Base:
    def __init__(self, list=[]):
        self.list = list

class Sub(Base):
    def __init__(self, item):
        Base.__init__(self, list=[])
        self.list.append(item)

x = Sub(1)
y = Sub(2)

print x.list   # prints [1]
print y.list   # prints [2]

Is there a way to avoid passing the argument explicitly in such cases? In my actual application, I have a lot of default values in my superclasses and it causes a lot of code duplication to pass them all again every time I initialize a subclass.

  • This is a slight variation of ["Least Astonishment" in Python: The Mutable Default Argument](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument) - If you address the issues there, your problem will vanish... – Jon Clements Jan 05 '14 at 15:12
  • Tl;dr: don't use mutable default arguments (or names that shadow Python built-ins!); use `lst=None` – jonrsharpe Jan 05 '14 at 15:15

1 Answers1

0

As Jon pointed out, you are mutating your default argument every time. If you want an empty list (but not the same one) to be the default, do this (noting how you set the new list to a full slice of the parameter):

class Base:
    def __init__(self, list=None):
        self.list = [] if list == None else list

class Sub(Base):
    def __init__(self, item):
        Base.__init__(self)
        self.list.append(item)

x = Sub(1)
y = Sub(2)

print x.list   # prints [1, 2]
print y.list   # prints [1, 2]

Incidentally, you should probably avoid naming any variables list since that is the name of the list type.

SeanTater
  • 182
  • 1
  • 5
  • This, however, is both wasteful and not always what one wants (`Base(please_mutate_this_list)`). –  Jan 05 '14 at 15:16
  • This is not good advice; if you want to use a mutable default argument, use `default=None` then `if default is None: default = []` – jonrsharpe Jan 05 '14 at 15:17
  • You're probably right; I'll change it. (But it's a duplicate anyway) – SeanTater Jan 05 '14 at 15:18