inherit and overwrite a property (better its method call)

Peter Otten __peter__ at
Mon Feb 16 23:17:41 CET 2004

chris wrote:

> hi,
> i am tinkering with properties of new style classes:
> class Base(object):
>      def m(self):
>          return 'p of Base'
>      p = property(m)
> class Sub(Base):
>      def m(self):
>          return 'p of Sub'
> b = Base()
> print b.p # prints 'p of Base'
> s = Sub()
> print s.p # prints 'p of Base'!?
> i was thinking s.p would use the method m of class Sub and not Base. but
> this does not work, both properties "p" of Base and Sub use method m of
> baseclass Base.
> so it seems i cannot overwrite the method p calls to get its value
> without actually repeating the property definition in every subclass, or
> is there a way? the following does work but i want to get rid of the
> second p = property(m)...
> class Sub(Base):
>      def m(self):
>          return 'p of Sub'
>      p = property(m)
> print b.p # prints 'p of Base'
> s = Sub()
> print s.p # prints 'p of Sub'
> am i missing something?

I don't think so. Anyway, I have been tinkering too, and here's what I've
come up with so far: 

class inheritableproperty(property):
    """ property with overridable accessor functions """

def funcByName(cls, fn):
    # helper func
    if fn is None: return None
    result = getattr(cls, fn.__name__, None)
    assert result is None or callable(result)
    return result

class typewithinheritableproperties(type):
    def __init__(cls, name, bases, dict):
        super(typewithinheritableproperties, cls).__init__(name, bases,
        # replace inheritable properties with new instances where
        # the accessors are determined by a name lookup in the actual class
        for name in dir(cls):
            a = getattr(cls, name)
            if isinstance(a, inheritableproperty):
                setattr(cls, name, inheritableproperty(
                    funcByName(cls, a.fget),
                    funcByName(cls, a.fset),
                    funcByName(cls, a.fdel)

class A(object):
    __metaclass__ = typewithinheritableproperties
    def geta(self): return "A.a"
    a = inheritableproperty(geta)

class B(A):
    def geta(self): return "B.a"

class C(A): pass
class D(B): pass

print A().a
print B().a
print C().a
print D().a might also be of interest for you.
It has an example of properties based on naming conventions (class


More information about the Python-list mailing list