2013-02-27 38 views
1

我想寫一個Python的property的子類,它已經有一個setter,它在設置之前對值進行了特定檢查。Python:編寫一個具有特殊設置行爲的「property」的子類

背景:我有一個有很多屬性的類,它們都不能是負面的。所以我想把它們全部轉換成屬性,並檢查它們是否設置了非負值。但我不想多次寫同一個setter。

請看看下面的例子:

class Body(object): 
    _mass = 0. 
    _size = 0. 

    @nonnegative 
    def mass(self): 
    return self._mass 

    @nonnegative 
    def size(self): 
    return self._size 

現在我想界定「非負」,這應該從「屬性」繼承。我擬設被覆蓋__set__的方法,但我堅持:

class nonnegative(property): 
    def __set__(self, obj, value): 
    if value < 0: 
     raise ValueError, 'value must not be negative' 
    ### then set the attribute to value, but how? 
    ### how can I know the name of the attribute? 

或者,也許我應該覆蓋fset?或setter?有人可以幫忙嗎?

回答

0

不simplier這樣的:

class Body(object): 
def __init__(self): 
    self._mass = 0. 
    self._size = 0. 

    self.last = True 

def __setattr__(self, name, val): 
    if 'last' in self.__dict__: 
     if val < 0: 
      raise ValueError('value must not be negative') 
      return 
    self.__dict__[name] = val 

def mass(self): 
    return self._mass 

def size(self): 
    return self._size 

「最後」是隻存在跳過您在初始化提供值。保持......最後。 很明顯,你可以檢查ATTR名不是保留/特殊的一個或者

if val < 0 

將檢查所有你在初始化後設置。

編輯:這將檢查當你設置的價值,而不是當你得到時的否定。如果你想允許負值,但上漲只檢索錯誤,使用

__getattr__ 

或(對於abarnert)以經典的方式,但你必須寫二傳手/ getter方法每個屬性:

class Body(object): 
    def __init__(self): 
     self._mass = 0. 
     self._size = 0. 

    @property 
    def mass(self): 
     return self._mass 

    @mass.setter 
    def mass(self, value): 
     if value < 0: 
      raise ValueError('value must not be negative') 
     self._mass = value 

    @mass.getter 
    def mass(self): 
     return self._mass 
+0

除了縮進問題外,這似乎並不符合OP的要求。首先,你必須執行'body.mass()'而不是'body.mass',所以它不是一個屬性。你必須做'body._mass = 3'而不是'body.mass = 3'。 (如果那不是真的,你根本不需要「最後一招」技巧。) – abarnert 2013-02-27 23:25:37

+0

@abarnert:關於財產的真實性,這是我問的方式:「不是這樣簡單」! – cox 2013-02-27 23:51:35

+0

你認爲一個你必須用'body.mass()'獲取值並用'body._mass'設置它的API是_simpler_而不是你得到和設置一致的API? – abarnert 2013-02-28 00:15:53

相關問題