class variable vs instance variable --Python

I tried this below example and need some clarification..In both the cases, I'm able to access the class variable and instance in test function.

So, assume if I have to define a literal that needs to be used across all function, which would be the better way to define..self variable or class variable?

code.py

class testclass:
    classvar = 'its classvariable LITERAL'
    def __init__(self,x,y):
        self.z = x
        self.classvar = 'its initvariable LITERAL'

        self.test()

    def test(self):
        print('class var',testclass.classvar)
        print('instance var',self.classvar)

if __name__ == '__main__':
    x = testclass(2,3)

Solution 1:

I know this is an old one.. but I found this in an old presentation made by Guido van Rossum in 1999 ( http://legacy.python.org/doc/essays/ppt/acm-ws/sld001.htm ) and I think it explains the topic beautifully:

Instance variable rules

On use via instance (self.x), search order:

  • (1) instance, (2) class, (3) base classes
  • this also works for method lookup

On assigment via instance (self.x = ...):

  • always makes an instance variable
  • Class variables "default" for instance variables

But...!

  • mutable class variable: one copy shared by all
  • mutable instance variable: each instance its own

Solution 2:

Class variables are quite good for "constants" used by all the instances (that's all methods are technically). You could use module globals, but using a class variable makes it more clearly associated with the class.

There are often uses for class variables that you actually change, too, but it's usually best to stay away from them for the same reason you stay away from having different parts of your program communicate by altering global variables.

Instance variables are for data that is actually part of the instance. They could be different for each particular instance, and they often change over the lifetime of a single particular instance. It's best to use instance variables for data that is conceptually part of an instance, even if in your program you happen to only have one instance, or you have a few instances that in practice always have the same value.

Solution 3:

It's good practice to only use class attributes if they are going to remain fixed, and one great thing about them is that they can be accessed outside of an instance:

class MyClass():
    var1 = 1
    def __init__(self):
        self.var2 = 2

MyClass.var1 # 1 (you can reference var1 without instantiating)
MyClass.var2 # AttributeError: class MyClass has no attribute 'var2'

If MyClass.var is defined, it should be the same in every instance of MyClass, otherwise you get the following behaviour which is considered confusing.

a = MyClass()
b = MyClass()

a.var1, a.var2 # (1,2)
a.var1, a.var2 = (3,4) # you can change these variables
a.var1, a.var2 # (3,4)
b.var1, b.var2 # (1,2) # but they don't change in b
MyClass.var1 # 1         nor in MyClass

Solution 4:

You should define it as a class attribute if you want it to be shared among all instances. You should define it as an instance variable if you want a separate one for each instance (e.g., if different instances might have different values for the variable).