1

I just got owned. I couldn't believe that this was true, but upon testing it, I found it to be:

class A(object):
    v = []

a = A()
b = A()

What do you think that the following code will return?

a.v is b.v

What about this code?

a.v.append(1)
a.v[0] == b.v[0]

Sure enough, a.v is b.v, they both share the same reference to the same list. Coming from a, well, every other programming language background, how does this make sense?

In Java, if I were to write a class like this:

class A {
    public Object[] v = new Object[]{};
}

...I would never, in my wildest dreams, think that two instances of the class would share the same reference to the array.

My main question is this, is there something equivalent for initial values in Python classes as in Java, C#, etc.? Why do all instances of the class share the same reference to the same list?

Naftuli Kay
  • 87,710
  • 93
  • 269
  • 411
  • That's because the equivalent java is actually `public static Object[] v = new Object[]{};` – Eric May 14 '13 at 06:13

4 Answers4

13

You have defined a class attribute instead of an instance attribute. Python is doing the right thing.

Instead of

class A(object):
    v = []               # Class attribute, shared across all instances!

you need

class A(object):
    def __init__(self):  # Instance attribute, created anew for each new object
        self.v = []
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
3

Java syntax is different to Python's. It's not a good idea to just try to guess the right thing to use based on your Java knowledge

class A(object):
    v = []  # class attribute


class A(object):
    def __init__(self):
        self.v = []  # instance attribute

Ok, the rules are kinda funny.

If you try to access self.v, first Python looks for an instance attribute, if there isn't one it looks at the class, and then the parent classes until it finds one or raises an attribute error.

When you assign to self.v it always binds it to an instance attribute even if it wasn't before.

Then there are descriptors...

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
2

That's because v is a class attribute (think static member variable in C++).

If you want a non-shared member attribute, you have to declare it in the constructor:

class A(object):
    def __init__(self):
        selv.v = []
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1
class A(object):
    v = []

here v is a class attribute not instance attribute, They are only defined once, during the class definition. So, that's why the're are pointing to the same object.

Use instance attribute instead:

class A(object):
    def __init__(self):
        self.v = []     #different for each instance
a= A()
b = A()
print a is b  #prints False
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504