For example:
class Example:
def __init__(self):
开发者_运维技巧 self.v = 0
@property
def value(self):
return self.v
@value.setter
def value(self, v):
self.v = v
class SubExample(Example):
pass
Would it be possible to rewrite just the getter to value in SubExample?
You can do so like this
class DoubleExample(Example):
@Example.value.getter
def value(self):
return self.v * 2
o = Example()
o.value = 1
print o.value # prints "1"
p = DoubleExample()
p.value = 1
print p.value # prints "2"
However, this only works if Example
is a new-style class (class Example(object):
) rather than an old style class (class Example:
), as it is in your example code.
Warning: Thomas pointed out in the comments that this method may not behave as expected if you're using multiple inheritance (class Foo(Bar, Baz)
).
It isn't possible to override a property's getter in a subclass, no. The property is an object that lives in the class and that holds references to the functions you give it -- if you later redefine the names of those functions, it won't affect the property at all.
What you can do is have the functions your property calls perform indirect calls, like so:
class Example(object):
def __init__(self):
self.v = 0
@property
def v(self):
return self._v_getter()
@v.setter
def v(self, value):
return self._v_setter(value)
def _v_setter(self, value):
self._v = value
class SubExample(Example):
def _v_getter(self):
return 5
>>> se = SubExample()
>>> se.v
5
>>> se._v
0
>>> se.v = 10
>>> se.v
5
>>> se._v
10
Alternatively, you can redefine the entire property in the subclass, by simply defining a new property. You won't have convenient access to the functions or property defined in the parentclass, however, and doing the right thing in the face of multiple inheritance is difficult.
Your question has been answered before:
http://code.activestate.com/recipes/408713-late-binding-properties-allowing-subclasses-to-ove/ http://stackoverflow.com/questions/3393534/python-property-and-method-override-issue-why-subclass-property-still-calls-the
Essentially, instead of using property
directly, you have to defer calling the getter so that it will access the one defined in the subclass rather than the one defined in the superclass when you first defined the property. This can be achieved via a lambda
:
class Test(object):
def __init__(self):
self.v = 0
def _value(self):
return self.v
def _value_setter(self, v):
self.v = v
value = property(lambda self: self._value(), lambda self, v: self._value_setter(v))
class Test2(Test):
def _value(self):
return self.v + 1
a = Test()
a.value = 2
print a.value # 2
b = Test2()
b.value = 2
print b.value # 4
精彩评论