Python:class Attribute/variable Inheritance With Polymorphism?
Solution 1:
a1.classvar = 'aaa'
This is not a "reference" to a class variable.
That is a new instance variable in the object 'a1'.
An expression like A.classvar
is the class variable. The class object (and it's superclasses) all have a class level dictionary (A.__dict__
) with class-level objects defined in it. Name resolution works by checking the class, then all the super-classes in Method Resolution Order (MRO).
An expression like a.classvar
is resolved by a search through the object's namespace. When this is a "reading" reference, the object and the class (and the superclasses) are searched.
When this appears on the left side of assignment, the instance variable ("classvar") is simply created on the referenced object ("a"). No searching through parent namespaces to resolve a name, since there's nothing to resolve. It's being created.
Solution 2:
If the implementation is hard to explain, it's a bad idea.
In this case, I am including an implementation, for sake of completness, and for this being the kind of tricky thing I like in Python.
Therefore, the snippet bellow abuse somewhat of closures to come up with a Class Decorator that fills the needs of the O.P. : a class variable that remains "unified" for reading and writing within derived classes.
Moreover, as a bonus, I wrap the attribute in a descriptor which makes the attribute unchangeable within instances as well - so whenever the attribute is written - in either a subclass or instance of a subclass of the original class, the class attribute is properly updated.
As the Zen of Python puts it: "If the implementation is hard to explain, it is a bad idea" - I don't think I could come with anything harder -- we are talking of scoped dynamically generated meta-classes here. It will work, but it looses this is "unpythonic" code as it is very cryptic due to the heavy use of the class, metaclass, closures and descriptor mechanisms.
defSingletonAttrs(**names):
keys = names.keys()
defclass_decorator(cls):
classMeta(type):
def__getattribute__(cls, attr):
if attr in keys:
returntype.__getattribute__(owner_cls, attr)
returntype.__getattribute__(cls, attr)
def__setattr__(cls, attr, value):
if attr in keys:
classWrapper(object):
def__init__(self, value):
self.__set__(None, value)
__set__ = lambda self, instance, value: setattr(owner_cls,"__" + attr, value)
__get__ = lambda self, instance, owner: type.__getattribute__(owner_cls, "__" + attr)
returntype.__setattr__(owner_cls, attr, Wrapper(value))
returntype.__setattr__(cls, attr, value)
owner_cls = Meta(cls.__name__, cls.__bases__, cls.__dict__.copy())
for key in keys:
setattr(owner_cls, key, names[key])
return owner_cls
return class_decorator
if __name__ == "__main__":
@SingletonAttrs(a="value 1", b="value 2")classTest(object):
passclassTestB(Test):
pass
t = Test()
print t.a
print t.b
tb = TestB()
tb.a = "value 3"print Test.a
Post a Comment for "Python:class Attribute/variable Inheritance With Polymorphism?"