2012-02-29 31 views
3

全部, 正如標題所述,是否有可能在運行時更改描述符的方法__get__。我處於一種在運行時正在進行裝飾和未裝飾的功能的情況。我希望此功能的結果作爲屬性提供,與@property相似。我研究了它,發現它是一個描述符,但似乎描述符的方法是隻讀的。您可以在運行時更改Python描述符的__get__方法嗎?

class Test(object): 
    def __init__(self): 
     self._x = 10 

    def get_x(self): 
     return self._x 

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

上面的代碼我想要做什麼,大致在

  1. 值在構造函數中設置
  2. 我可以裝點get_x方法對我的心臟的內容
  3. instance.x回報正確的值

我的問題是,我寧願不必因爲它基本上是不必要的,因此創建get_x方法。我只是無法裝飾x的__get__方法,因爲它是隻讀的。

背景

我正在寫一個回合策略遊戲,和我使用的裝飾來實現持續的條件。當我使用測試用例時,我能夠有效地實現這些裝飾器,但問題是要獲得計算值,則必須使用函數調用,而不是屬性訪問。這似乎是一個糟糕的主意,因爲獲取描述單元的值會不一致地使用函數或屬性。如果可以,我想標準化屬性。

回答

4

您可以覆蓋默認的「只讀」 property__get__屬性的特性使用簡單的繼承:

class MyProperty(property): pass 

class Test(object): 
    def __init__(self): 
     self._x = 10 

    def get_x(self): 
     return self._x 

    @MyProperty 
    def x(self): 
     return self.get_x() 

test = Test() 

現在的問題是,即使你重新定義你的Text.x財產__get__ attribure,在test.x要求Python運行時會調用MyProperty.__get__(Test.x, test, Test)

所以,你可以重寫它只有在那裏像

MyProperty.__get__ = lambda self,instance,owner: ""the x attribute" 
這裏

所以很好的選擇是委託調用一些redifineable屬性像

MyProperty.__get__ = lambda self,instance,owner: self.get(instance,owner) 

從現在起讓你的財產的屬性,在完全控制。 也有不好的選項爲每個屬性類對象生成單獨的類型。 因此,在良好的情況下,你可以這樣做:

class MyProperty(property): 
    def __get__(self,instance,owner) : 
     if not instance: return self 
     else: return self.get(instance,owner) 

class Test(object): 
    def __init__(self): 
     self._x = 10 

    def get_x(self): 
     return self._x 

    @MyProperty 
    def x(self): pass 

    @MyProperty 
    def y(self): pass 

    x.get = lambda self,clazz: self.get_x() 
    y.get = lambda self,clazz: "the y property of " + clazz.__name__ + " object" 

>>> test = Test() 
>>> test.x 
10 
>>> test.y 
'the y property of Test object' 
+0

謝謝,我會考慮這是今天,但它看起來像它做我想要的。如果一切正常,我會接受答案。 – mklauber 2012-02-29 15:45:50

相關問題