2

The following code describes what I mean:

class Demo(object):

    def __init__(self, data=[]):
        self.data = data

    def add(self, item):
        self.data.append(item)

    def get_data(self):
        return self.data

    def clear(self):
        self.__init__()

demo = Demo()

demo.add(1)
demo.add(2)
demo.clear()

print(demo.get_data())

I would expect it to print out []. Surprisingly, it does not.

I have to rewrite the class to fix it:

class Demo2(object):

    def __init__(self, data=[]):
        self.init(data)

    def init(self, data=[]):
        self.data = data

    def add(self, item):
        self.data.append(item)

    def get_data(self):
        return self.data

    def clear(self):
        self.init()

    demo = Demo2()

    demo.add(1)
    demo.add(2)
    demo.clear()

    print(demo.get_data())

It correctly prints out [] this time.

What is special of python class's __init__() method? It appears as if its argument is cached.

azalea
  • 11,402
  • 3
  • 35
  • 46
  • 1
    For the record, _all_ default arguments are cached, not just `__init__`. – ShadowRanger Mar 13 '17 at 20:51
  • 1
    _It correctly prints out [] this time_ ... only once. Try `demo.add(1); demo.clear(); demo.add(2); demo.clear(); print(demo.get_data())` – mata Mar 13 '17 at 20:52

1 Answers1

1

Your default argument [] is only evaluated once when the class is defined. You need to do something like the following:

def __init__(self, data=None):
    if data is None:
        data=[]
    self.init(data)

or

def __init__(self, data=[]):
    self.data = data[:]

Also, this is purely a stylistic thing, but I would recommend moving this logic into a different function called reinitialize or something, rather than having clear call __init__.

Greg Nisbet
  • 6,710
  • 3
  • 25
  • 65