0

I am new to Python, and noticed something I believe its a bug.

Edit 2011-09-30: Forget it. Now I know the attributes created are static and shared between the instances. Hope this thread helps another python newbies in the same situation as mine.

Consider the following code:

class test():

    dictionary1 = {}
    list1 = []

    def method1(self):
        self.dictionary1.update({'1': 'unique entry'})
        self.list1 = ['unique list entry']

t=test()

print 'dictionary1 value:', t.dictionary1
print 'list1 value:', t.list1
t.method1()
print 'dictionary1 new value:', t.dictionary1
print 'list1 new value:', t.list1

t2=test()
print 'dictionary1 value:', t2.dictionary1, " -- error -- I just instantiated the class. The correct value would be {}"
print 'list1 value:', t.list1
t2.method1()
print 'dictionary1 new value:', t.dictionary1
print 'list1 new value:', t.list1

Now the question:

Why in line 19 the executed code shows: {'1': 'unique entry'}. I belive it would be: {} Note that the list has the correct value: [] (empty list in line 20)

Using Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2

Sorry not so good english. From Brazil.

Edit 2011-09-30: Forget it. Now I know the attributes created are static and shared between the instances. Hope this thread helps another python newbies in the same situation as mine.

Tarmac
  • 95
  • 5
  • 24
    Rule no. 1: The bug is in your code or in your understanding of the feature, not in that mature, well-tested implementation. –  Jun 28 '11 at 17:23
  • 2
    Your code is totally broken. Post something that actually runs. – Daenyth Jun 28 '11 at 17:23
  • Is the indent for `self.list1 = ['unique list entry']` correct? It looks like it isn't inside `method1`. – thegrinner Jun 28 '11 at 17:24
  • you *overwrite* the list, and update the existing dictionary. That's why you think the list is unchanged – Riccardo Galli Jun 28 '11 at 17:25
  • 4
    It does what it should: you're using a [static class variable](http://stackoverflow.com/questions/68645/static-class-variables-in-python/68672#68672). – trutheality Jun 28 '11 at 17:29
  • 1
    The problem is not the "not so good english" but a significant lack of understanding object oriented programming in Python –  Jun 28 '11 at 17:29
  • And [the list behaves just like the dictionary](http://ideone.com/IG6AD) – trutheality Jun 28 '11 at 17:32
  • 3
    @Tarmac - In clear English: Please don't say you've found a bug unless you're *absolutely sure* it's not your fault. People get annoyed if it looks like you're blaming others. – Thomas K Jun 28 '11 at 17:33
  • 4
    Please don't be mean with the OP, he did said he's new. Please do not bite the newcomers. – Evpok Jun 28 '11 at 19:06
  • 1
    So sorry for thinking it was a bug. I just asked if it was a bug. Maybe my poor english made it unclear. – Tarmac Jun 30 '11 at 13:22
  • Now I understand I made a confusion just based on my other programing languages knowledge. – Tarmac Jun 30 '11 at 13:23

3 Answers3

14

All your instances of test class share the same dictionary and list. The correct way to initialize the members would be:

class Test():
    def __init__(self):
        self.dictionary1 = {}
        self.list1 = []

Attributes assigned directly in the class body will be evaluated once and then shared between all instances. Since the __init__ method is run once per instance, a new list and dictionary will be created for each instance.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • 3
    And they share them because what OP declared were class variables (similar to `static` members in other languages). –  Jun 28 '11 at 17:24
7

Variables directly declared in the class body (static class variables) are shared among all instances of the class. Therefore, it's not a good idea to change them.

Instead, initialize object member variables in the constructor:

class test(object):
    def __init__(self):
        self.dictionary1 = {}
    def method1(self):
        self.dictionary1.update({'1': 'unique entry'})
Community
  • 1
  • 1
phihag
  • 278,196
  • 72
  • 453
  • 469
5

To add to the other answers, the reason you see different behaviour for the dict and the list is: when you write self.dictionary1.update({'1': 'unique entry'}), you change the contents of self.dictionary1, but it's still the same dict object. When you write self.list1 = ['unique list entry'], you replace self.list1 with a new list object. You would get the same behaviour as with the dict by doing: self.list1.append('unique list entry').

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153