2016-05-19 31 views
0

我想从包含属性x的类继承,然后通过重写setter将此属性设置为子类中的只读属性。如果父类中的__init__使用原始设置器,则这不起作用。考虑下面的代码。Python:重写属性时发生意外的行为

class Parent: 
    def __init__(self, x=1): 
     # I want the following line to use the setter defined in the Parent 
     # class, even when __init__ is called from Child using super. 
     self.x = x 
     # Other initialization of Parent goes here. 

    @property 
    def x(self): 
     return self._x 

    @x.setter 
    def x(self, value): 
     """Check that x is non-negative.""" 
     if value < 0: 
      raise ValueError("x must be non-negative.") 
     self._x = value 


class Child(Parent): 

    def __init__(self): 
     super().__init__() # Need this for initialization. 

    @property 
    def y(self): 
     return self._y 

    @y.setter 
    def y(self, value): 
     """x can only be written to implicitly by setting y.""" 
     self._y = value 
     self._x = abs(value) 

    @property 
    def x(self): 
     return self._x 

    @x.setter 
    def x(self, value): 
     raise AttributeError("Illegal access to x") 

如果我现在尝试实例Child,我得到AttributeError: Illegal access to x,因为当行self.x = x叫的Childx二传手被调用,而不是x二传手Parent。我怎样才能以Python方式使用Parent的setter?

需要明确的是,当self.x = ...出现在Parent的方法,它应该总是利用x二传手在Parent,当self.x = ...出现在Child的方法,它应该总是利用x二传手在Child ,从而引发异常。

+0

你不能继承这样的属性,你可以这样做:'Child.x = Parent.x.setter(Parent.x.fset)'类初始化后。 –

+0

@AshwiniChaudhary这是行不通的。它不会为'Child'使'x'只读。 –

回答

1

我设法在Parent.__init__

Parent.x.fset(self, x) 

换出

self.x = x 

我也可以在Child如果代替摆脱

@property 
def x(self): 
    return self._x 

来解决自己的问题@x.setter,我用@Parent.x.setter

+0

'@ Parent.x.setter'在子中不会使'x'为只读。 –

+0

@NizamMohamed是的,它会的,因为试图写入孩子'x'会引发一个'AttributeError'。 –