Overriding properties in python
Solution 1:
The Python docs on the property
decorator suggest the following idiom:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
And then subclasses can override a single setter/getter like this:
class C2(C):
@C.x.getter
def x(self):
return self._x * -1
This is a little warty because overriding multiple methods seems to require you to do something like:
class C3(C):
@C.x.getter
def x(self):
return self._x * -1
# C3 now has an x property with a modified getter
# so modify its setter rather than C.x's setter.
@x.setter
def x(self, value):
self._x = value * 2
Of course at the point that you're overriding getter, setter, and deleter you can probably just redefine the property for C3.
Solution 2:
I'm sure you've heard this before, but apply
has been deprecated for eight years, since Python 2.3. Don't use it. Your use of locals()
is also contrary to the Zen of Python -- explicit is better than implicit. If you really like the increased indentation, there is no need to create a throwaway object, just do
if True:
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, val):
self._foo = val
Which doesn't abuse locals
, use apply
, require creation of an extra object, or need a line afterwards with foo = foo()
making it harder to see the end of the block. It works just as well for your old-fashioned way of using property
-- just do foo = property(fget, fset)
as normal.
If you want to override a property in an arbitrary subclass, you can use a recipe like this.
If the subclass knows where the property was defined, just do:
class ATimesTwo(A):
@A.foo.setter
def foo(self, val):
self._foo = val * 2