Search code examples
python-3.xinheritancestatic-variables

Confused about static class vars in python


Here a little example code:

class A:
    staticvar=3;

    def foo2(self):
        print("------ Foo2")
        print("static: "+str(A.staticvar));
        print("instance: "+ str(self.staticvar));

class B(A):

    def setStaticVar(self, num):
        B.staticvar=num;


a=A();
b=B();

a.staticvar=7;
a.foo2();

b.setStaticVar(100);

a.foo2();

b.foo2();

what results in:

------ 
static: 3
instance: 7  -->correct. Instance var modified
------ 
static: 3
instance: 7  --> Not correct. Why static var is not 100
------ 
static: 3
instance: 100 --> Correct, but this value should be shared between A and B

Why is this happening? Shouldn't the static variable be shared between A and B? Why when it is modified in b through b.

From this example it seems, each class has its own static var (not really static from my point of view because there would only be one static var and we have 2, one per class).

Could anyone explain this behaviour?

Cheers.


Solution

  • I suspect what you're running into is an issue of name resolution. When you get B.staticvar, the interpreter fails to find it and falls back on its super classes to try to resolve the name. Upon traversing to A, the interpreter finds staticvar and returns the value.

    When you set a value to B.staticvar, however, you get much the same behavior as your "instance" case, where a new property called staticvar is added to B. Now, when it attempts to resolve the property name on B (or instances thereof), it uses this new value without ever falling back to A. In Python, inheriting a class isn't much about sharing its properties, it's about setting a fallback class to resolve names when they aren't defined in your child class (hence why there's no need to explicitly "override" methods, and why you must remember to call super(A).method_name within B.method_name if you want the parent function to be run).

    To get the behavior you're asking for, either define setStaticVar in A, and/or change its body to A.staticvar=num