Skip to content Skip to sidebar Skip to footer

Python:class Attribute/variable Inheritance With Polymorphism?

In my endeavours as a python-apprentice i got recently stuck at some odd (from my point of view) behaviour if i tried to work with class attributes. I'm not complaining, but would

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?"