class variables is shared across all instances in python?

45,549

Solution 1

var should definitely not be shared as long as you access it by instance.var or self.var. With the list however, what your statement does is when the class gets evaluated, one list instance is created and bound to the class dict, hence all instances will have the same list. Whenever you set instance.list = somethingelse resp. self.list = somethingelse, it should get an instance level value.

Example time:

>>> class A():
...     var = 0
...     list = []
...
>>> a = A()
>>> b = A()
>>> a.var
0
>>> a.list
[]
>>> b.var
0
>>> b.list
[]
>>> a.var = 1
>>> b.var
0
>>> a.list.append('hello')
>>> b.list
['hello']
>>> b.list = ['newlist']
>>> a.list
['hello']
>>> b.list
['newlist']

Solution 2

These are basically like static variables in Java:

// Example equivalent Java
class A {
    static int var = 0;
    static String[] list;
}

This is the intended behavior: Class variables are for the class.

For normal instance variables, declare them in the constructor:

class A:
    def __init__(self):
        self.var = 0
        self.list = []

You may want to look at Static class variables in Python.

Solution 3

The reason is that in Python class is an executable statement that is executed like any other. The body of the class definition is executed once, when the class is defined. If you have a line line var = [] in there, then it is only executed once, so only one list can ever be created as a result of that line.

Solution 4

Note that you do not see this behaviour for var, you only see it for list:

>>> class A:
...     var = 0
...     list = []
... 
>>> a1 = A()
>>> a2 = A()
>>> a1.var = 3
>>> a2.var
0
Share:
45,549
howtechstuffworks
Author by

howtechstuffworks

I am Student from an university in North East. I had a bad habit of coding in a language, just by seeing examples and browsing/googling syntax online, thats how I completed most of my assignments, but better late than never, I realized that this is a problem, when you go into research, where you need to think in terms of language and understand the underlying mechanisms to become a better coder, which is what after all, I am striving for. Anyways, I think I will learn more here, than I could ever contribute.

Updated on October 28, 2020

Comments

  • howtechstuffworks
    howtechstuffworks over 3 years

    I started coding in python a week ago, it is my mistake i started coding using oops,classes and objects that soon. I assumed my C++ proficiency will help.... I got bit by the following code

    class A:
         var=0
         list=[]
         def __init__(self):
                pass
    

    Here to my surprise, var and list are kinda global variable, it is shared across all instances it seems.... What I thought was it was different across all the instances..... It took me half a day to figure out that.... It does not make even slightest sense, that a variable can be accessed by a class object only, but is shared across all instances....... Just Curious, is there a reason behind it?????

  • howtechstuffworks
    howtechstuffworks almost 12 years
    ^yeah agreed.... but still confusing....
  • Brendan Long
    Brendan Long almost 12 years
    This is because Python looks for an instance variable before the class variable. In your var case, you're adding an instance variable, which then takes precedence.
  • howtechstuffworks
    howtechstuffworks almost 12 years
    okay, now I tried an exmaple and pretty sure, the list is shared across all.... How about the variable? it is not shared across all instances(I tested it)..... is it still static, do I need to learn anymore before proceeding back to the code.... Thanks for your help.......
  • Brendan Long
    Brendan Long almost 12 years
    @howtechstuffworks The other variable is static too, but if you do self.var="something else", then you're setting up an instance variable with the same name (you will have both A.var and self.var), and it will assume that you mean the instance variable. You can still access the class variable with A.var. You can do the same thing with the list by declaring an instance method with the same name (self.list = "something else").
  • Brendan Long
    Brendan Long almost 12 years
    The exact same thing is happening with var as with list, the difference is that you can't append to var like you can with list, you can only declare another variable with the same name.
  • howtechstuffworks
    howtechstuffworks almost 12 years
    Yeah actually I moved everything under '__init__()', just another question, I have some variables that needs to be common and not writable..... think like a macro in C or const in C++, where should I write it here????
  • Brendan Long
    Brendan Long almost 12 years
    @howtechstuffworks You should generally open a new thread for each question, but to answer -- Python doesn't have constants. There are some hacks to create them, but the general solution is to name constants in upper case and assume users of your API aren't stupid enough to change them (you'll find this is a common theme in Python -- you can do anything, but just because you can doesn't mean you should).
  • mensi
    mensi almost 12 years
    @BrendanLong immutable types are different in this situation, since it does not matter if you share them
  • Brendan Long
    Brendan Long almost 12 years
    Yes, I just want to clarify that you are sharing the immutable var, you're just also replacing it with something else whenever you do self.var = .... So the behavior is exactly the same for var and list, it's just that list is more interesting as a shared variable (since it's mutable).
  • F.S.
    F.S. almost 7 years
    @BrendanLong why is var an instance variable, and list is not, if they are defined in the same way?
  • Gertjan Franken
    Gertjan Franken almost 4 years
    This behavior of mutable default arguments is also discussed here: docs.python-guide.org/writing/gotchas/…