2016-05-19 48 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'。 –