overriding a property

Hrvoje Niksic hniksic at xemacs.org
Wed Oct 20 11:25:53 EDT 2010


Lucasm <lordlucraft at gmail.com> writes:

> Thanks for the answers. I would like to override the property though
> without making special modifications in the main class beforehand. Is
> this possible?

That will not be easy.  When you access obj.return_five, python looks up
'return_five' in type(obj) to see what the return_five property even
means.  (See http://users.rcn.com/python/download/Descriptor.htm for
details of how this works.)

Since you can't change the source of A, you are left with two options:
you can monkey-patch A.return_five to make it optionally consult the
instance, or you can assign to instance's __class__ to make it point to
a subclass of A that implements a different 'return_five'.  Both options
are fairly unpleasant, but I think I'd go with the first one.

Others have spelled out the __class__-changing variant.  While
monkey-patching is not the cleanest of practices to adopt, in my mind it
still beats assigning to __class__.  Here is an example:

# Wrap return_five so it supports per-instance customization, but
# without copy-pasting the original.
def wrap_return_five(orig):
    @property
    def wrapper(self):
        if 'return_five' in self.__dict__:
            return self.__dict__['return_five']
        return orig.__get__(self, type(self))
    return wrapper

>>> A.return_five = wrap_return_five(A.return_five)
>>> a = A()
>>> b = A()
>>> a.return_five
5
>>> a.__dict__['return_five'] = 10
>>> a.return_five
10
>>> b.return_five
5

If you want, you can make a.return_five itself settable, but I'll leave
that as an excercise for the reader.



More information about the Python-list mailing list