I have a hierarchy of objects in a python module as follows:
class BaseObject(object):
initialized = False
def __init__(self):
self._initialize()
@classmethod
def _initialize(cls):
print "cls.initialized = "+str(cls.initialized)
if not cls.initialized:
cls.x = 1
cls.initialized = True
class ObjectOne(BaseObject):
@classmethod
def double_x(cls):
cls.x = cls.x * 2
print cls.x
class ObjectTwo(BaseObject):
@classmethod
def triple_x(cls):
cls.x = cls.x * 3
print cls.x
if __name__ == '__main__':
obj_1 = ObjectOne()
obj_1.double_x()
obj_2 = ObjectTwo()
obj_2.triple_x()
When I run this module I would like the output to be:
cls.initialized = False
2
cls.initialized = True
6
But what I get is:
cls.initialized = False
2
cls.initialized = False
3
What do I not understand?
You need to use the full classname to set class variables.
clsindouble_xandtripple_xwill refer to subclasses (ObjectOneandObjectTwo, respectively), and setting attributes on those subclasses will store new variables, not alter the class variableBaseObject.x. You can only alter base class variables by directly accessing them.Using your code, we get:
What happened is that in
_initialize(),clswas set toObjectOneorObjectTwo, depending on what instance you created, and each subclass got their own copies of the variablesinitializedandx.Using
BaseObject._initialize()(to ensure thatBaseObjectis initialized, and not the subclasses) gives:So now
_initialize()usedBaseObjectas the target to setinitializedand the initial value forx, butdouble_xandtriple_xstill used their own subclasses to set the new value ofxand are not sharing that value throughBaseObject.The only option you have to set class variables on a specific base class is to refer to it directly in all class methods:
which would give:
Note that I called
BaseObject._initialize()to make sure thatclsisBasObjectand not a subclass. Then, when settingxthedouble_xandtriple_xmethods still refer directly toBaseObjectto ensure that the variable is set directly on the base class. When reading the value ofxthe above example still usescls, which uses the class MRO to findxon the base class when not set locally.