Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python instances and attributes: is this a bug or i got it totally wrong?

Suppose you have something like this:

class intlist:
        def __init__(self,l = []):
                self.l = l
        def add(self,a):
                self.l.append(a)

def appender(a):
        obj = intlist()
        obj.add(a)
        print obj.l

if __name__ == "__main__":
        for i in range(5):
                appender(i)

A function creates an instance of intlist and calls on this fresh instance the method append on the instance attribute l.

How comes the output of this code is:

[0]

[0, 1]

[0, 1, 2]

[0, 1, 2, 3]

[0, 1, 2, 3, 4]

? If i switch

obj = intlist()

with

obj = intlist(l=[])

I get the desired output

[0]

[1]

[2]

[3]

[4]

Why this happens?

Thanks

like image 516
Mirko Rossini Avatar asked Mar 08 '10 16:03

Mirko Rossini


2 Answers

Ah, you've hit one of the common Python gotchas: default values are computed once, then re-used. So, every time __init__ is called, the same list is being used.

This is the Pythonic way of doing what you want:

def __init__(self, l=None):
    self.l = [] if l is None else l

For a bit more information, check out the Python docs (especially about three paragraphs after that heading).

Edit: There is a much better description in another answer.

like image 69
David Wolever Avatar answered Oct 04 '22 05:10

David Wolever


When you set the default value of l=[] in __init__, you're actually using the same list each time. Instead, you could try something like:

class intlist:
    def __init__(self, l=None):
        if l is None:
            self.l = []
        else:
            self.l = l
like image 23
Michael Williamson Avatar answered Oct 04 '22 04:10

Michael Williamson