override a property

Kay Schluehr kay.schluehr at gmx.net
Sat Oct 22 15:46:42 CEST 2005

Robin Becker wrote:
> Kay Schluehr wrote:
> > Robin Becker wrote:
> >
> >
> >>I thought that methods were always overridable.
> >>In this case the lookup on the
> >>class changes the behaviour of the one and only property.
> >
> >
> > How can something be made overridable that is actually overridable? I
> > didn't know how to better express the broken polymorphism of Pythons
> > properties than by stating it as a pleonasm about the used get and set
> > methods. This way a property don't ever have to be redefined in
> > subclasses if get_x, set_x etc. are changed.
> >
> > Kay
> >
> well I guess that's the ambiguity of human language. Clearly when I
> assign to a normal attribute I am changing its value; assigning to a
> property or descriptor does something that is not so obvious. Changing
> the behaviour of such an attribute could be done by inheritance as
> suggested. The new class has overridden the property. When I want to do
> that on an instance I have first to create a mutable version of the
> descriptor where the mutability is on the instance not the class. I call
> the action of changing the base descriptor behaviour 'overriding', but
> perhaps that's not the correct word. What do you suggest?
> --
> Robin Becker

I would suggest to take a step back and start with Raymond Hettingers
descriptor definition:

"In general, a descriptor is an object attribute with "binding
behavior", one whose attribute access has been overridden by methods in
the descriptor protocol. Those methods are __get__, __set__, and
__delete__. If any of those methods are defined for an object, it is
said to be a descriptor."


The definition is a little confusing since we have to identify the
descriptor object that implements one of the descriptor methods
__get__, __set__ and __del__ with an object attribute that is assigned
by the descriptor ( as object not attribute ). Otherwise we can assert
that a descriptor becomes effective only if it is used as an object
attribute. The meaning / essence of a descriptor is to assign
attributes by a descriptor to alter binding behaviour but it's
essentially an object that can be handled quite differently. To make
the destinction clear I will talk about "descripted" attributes.

Now we can talk unambigously about "overriding" the descriptor by means
of overriding the descriptor methods in subclasses. In case of
"properties" we pass certain functions into property() that will be
wrapped into descriptor methods. Thereby property() is itself a
descriptor. If we use methods of the class where the descripted
attribute is defined, overriding has no effect on the descriptor. The
inheritance hierarchies of descriptors and classes that define
descripted attributes do not correspond.

One way of establishing a pseudo-correspondence I've already presented.
But maybe one can do it better without decorators? Remember that
property() is a descriptor factory and there is no intrinsic need to
pass functions into a factory function. Why not passing strings that
are names of methods?

For brevity only __get__ should be defined here:

class described_by(object):
    def __init__(self, fget=""):
        assert isinstance(fget, str)
        self.fget = fget

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError, "unreadable attribute"
        return getattr(obj.__class__, self.fget)(obj)

class A(object):
    def __init__(self, x):
        self._x = x

    def get_x(self):
        return self._x

    x = described_by("get_x")

class B(A):
    def get_x(self):
        return self._x**2

>>> a = A(7)
>>> a.x
>>> b = B(7)
>>> b.x


More information about the Python-list mailing list