Sil*_*Ray 2 python overriding properties
所以我有这个:
class Parent(object):
def __init__(self, val):
print 'enter Base init'
self._set_x(val)
print 'leave Base init'
def _get_x(self):
return self._x
def _set_x(self, val):
print 'enter Base _set_x'
self._x = val
print 'leave Base _set_x'
x = property(_get_x, _set_x)
class Child(Parent):
def _set_x(self, val):
print 'enter Child _set_x'
y = val * 2
super(Child, self)._set_x(y)
print 'leave Child _set_x'
child = Child(5)
num = child.x
child.x = 5
print num == child.x
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到了这个:
enter Base init
enter Child _set_x
enter Base _set_x
leave Base _set_x
leave Child _set_x
leave Base init
enter Base _set_x
leave Base _set_x
False
Run Code Online (Sandbox Code Playgroud)
我一直在读书,人们都说最重要的不应该奏效,但我的问题是为什么这里看似不一致?从init调用时,子类'setter被调用,但是当你稍后对已经初始化的对象进行操作时,它会调用base的setter.有人能解释一下这里发生了什么吗?
因为你不一致地称它 - 一次直接,一次通过一个属性.改变self._set_x(x)在Parent.__init__给self.x = x,你会看到Child._set_x永远不会被调用.要覆盖子类中的setter,可以使用property.setteras decorator:
class Child(Parent):
@Parent.x.setter
def x(self, arg):
super()._set_x(arg)
Run Code Online (Sandbox Code Playgroud)
或者为属性添加一个间接级别:
class Parent(object):
# ...
x = property(
lambda self: self._get_x(),
lambda self, x: self._set_x(x)
)
Run Code Online (Sandbox Code Playgroud)
覆盖不能直接起作用,因为属性存储具体的方法对象(Parent._get_x和Parent._set_x),并且不会再次查找它们,即使对象的类型发生了变化 - 运行的代码也是相同的.间接强制在动态类型中查找self,允许覆盖.