March 26, 2006

Note to self - Python properties are non-polymorphic.

Properties are just one application of Python ubiquitous proxying. The properties are created as wrappers over get/set methods:
class C(object):

def __init__(self, value):
self._value = value

def _get_value(self):
return self._value

value = property(_get_value)

# all is fine, value calls C._get_value:

assert C(10).value == 10

Here is what's happening: an instance of a property class is created and a reference to C._get_value is stored in it. Next time c.value is referenced, the property calls the original method.

The problem is, the reference is bound to the particular class C, and so if you inherit from it, you should not expect the property to be rebound to the ancestor class'es method:
class D(C):

def _get_value(self):
return self._value + 1

# now, this still calls C._get_value:

assert D(10).value != 11

The properties are thus non-polymorphic. There is one way to make them such by introducing late binding,
class C(object):

...

value = property(lambda self: self._get_value())

but I personally find it cumbersome.

1 comment:

Anonymous said...

That type of late binding works for gets, but I have not yet found a way to make it work for setting a property.
Has anyone had luck figuring this out?