0

When I execute this python code it generates the output below.

class A(object):
    a = 0
    n = {}

    def inc(self):
        self.a += 1

    def add(self, key, obj):
        self.n[key] = obj

    def printn(self):
        print self.a
        print self.n


b = A()
c = A()

b.add("asf", "----")
c.add("asdf", "====")

b.inc()
c.inc()

b.printn()
c.printn()

Output:

1
{'asf': '----', 'asdf': '===='}
1
{'asf': '----', 'asdf': '===='}
laltin
  • 1,134
  • 12
  • 20
  • 2
    Beside being a duplicate, this also isn't a very good question in the sense that the only indication of what you're asking is something vague about, I guess, it not doing what you expected. Generally the more specific you are, the better folks will be able to help you. – martineau Aug 31 '13 at 00:10

2 Answers2

5

The problem has nothing to do with n being a dictionary; it's that n is a class attribute instead of an instance attribute. That means all instances of the class share a single value.

The solution is simply to turn it into an instance variable—assign it inside a method (usually the __init__ method) instead of inside the class definition.

class A(object):
    def __init__(self):
        self.n = {}

You may ask why the same thing doesn't happen with a. Well, it does. You're creating a single shared a, just as with n.

But you're not calling any methods on that shared a that change it (in fact, you can't, because int is immutable; it doesn't have any methods that change it). With n, that self.n[key] = object may not look like an method call (it's actually self.n.__setitem__(key, object)), but it's obvious that it's changing the value of n in-place, which is the key here.

You're just assigning a new value to self.a. That creates a new instance attribute that shadows the class attribute of the same name—which is confusing, but it works as you want it to. You could get the same behavior with n if you wanted just by building a new value and assigning it to self.n:

def add(self, key, obj):
    new_n = copy.copy(n)
    new_n[key] = obj
    self.n = new_n
abarnert
  • 354,177
  • 51
  • 601
  • 671
0
n = {}

This doesn't do what it would in other languages. In other languages, you might expect this to declare an instance attribute that would always be initialized with an empty dict. In Python, it creates a class attribute. All instances share the same n.

To fix it, write a constructor and set the attribute on self:

def __init__(self):
    self.a = 0
    self.n = {}
user2357112
  • 260,549
  • 28
  • 431
  • 505