In my endeavors, as a python student, I recently got stuck in some odd (from my point of view) behavior if I tried to work with class attributes. I am not complaining, but I will be grateful for some useful comments to shed light on this issue.
To reduce a complex question to a more concise question, I would formulate it like this:
What is the "pythonic" way to make sure that the class attribute behaves more like a static variable in an inheritance tree?
It seems to me that the class attribute behaves like the default “copy by read” value with polymorphic characteristics. While I perform read-only operations, it remains "single", but as soon as I access the class attribute with the assignment through a derived class or instance, it turns into a new link, losing contact with the inherited link base.
(It has the potential for some interesting features, but you should understand this by hugging it, so understanding is greatly appreciated.)
class A(object): classvar = 'A' def setclassvar(self, value): A.classvar = value def __str__(self): return "%s id(%s) " %(A.classvar, hex(id(A.classvar))[2:-1].upper()) class A1(A): pass class B(object): classvar = 'B' def setclassvar(self, value): self.__class__.classvar = value def __str__(self): cvar = self.__class__.classvar return "%s id(%s) " %(cvar, hex(id(cvar))[2:-1].upper()) class B1(B): def setclassvar(self, value): self.__class__.classvar = value a, a1 = A(), A1() a1.setclassvar('a') print "new instance A: %s" %a print "new instance A1: %s" %a b, b1 = B(), B1() b1.setclassvar('bb') print "new instance B: %s" %b print "new instance B1: %s" %b1 a1.setclassvar('aa') print "new value a1: %s" %a print "new value a: %s" %a a1.classvar = 'aaa' print "direct access a1: %s id(%s)" %(a1.classvar, hex(id(a1.classvar))[2:-1].upper()) print "method access a1: %s" %a1 print "direct access a: %s" %a
produces the following:
new instance A: a id(B73468A0) new instance A1: a id(B73468A0) new instance B: B id(B73551C0) new instance B1: bb id(AD1BFC) new value a1: aa id(AD1BE6) new value a: aa id(AD1BE6) direct access a1: aaa id(A3A494) method access a1: aa id(AD1BE6) direct access a: aa id(AD1BE6)
Thus, direct (assigning) access to object.classvar or indirect via self.__class__.classvar does not match BASECLASS.classvar .
Is this a problem of the area or something completely different.
We are waiting for your answers and thank you in advance. :-)
Edit: for a short time there was an answer involving the use of class descriptors: How to create a class property? .
Unfortunately this does not work:
class Hotel(Bar): def __init__(self): Hotel.bar += 1 hotel = Hotel() assert hotel.bar == 51 assert hotel.bar == foo.bar
The second statement fails! hotel.bar does not refer to the same object as foo.bar , and hotel.bar refers to others other than Hotel.bar!
2nd Edit: I understand very well that singletones are considered an "antipatter", and I was not going to use them (extensively). Therefore, I did not mention them in the tile question. However, there are many solutions that discuss and provide solutions with and about singletones, my question remains: why does a class variable easily separate a link? Ruby behaves as it seems natural to me: http://snippets.dzone.com/posts/show/6649