2012-12-14 38 views
2

我有一個類,看起來像這樣:修改通過方法裝飾類屬性

class Test(object): 
    data = {} 

    @add_to_data(1) 
    def method_1(self, x, y): 
     pass 

    @add_to_data(1, 2, 3) 
    def method_2(self, x, y): 
     pass 

    @add_to_data(5, 6, 7) 
    def method_3(self, x, y): 
     pass 

我想它,以便在「導入時間」的data屬性附加傷害之類的是:

>>> Test.data 
{'method_1': [1], 'method_2': [1, 2, 3], 'method_3': [5, 6, 7]} 

目前我有這個(datadefaultdict):

def add_to_data(*items): 
    def decorator(func): 
     for item in items: 
      name = func.__name__ 
      cls = ?? 
      cls.data[name].append(item) 
     return func 
    return decorator 

但我不知道如何獲得類對象。任何幫助?

回答

3

它不是特別乾淨,但你可以使用sys._getframe()檢查呼叫範圍內做到這一點(裝飾將在類的定義,其中data是一個局部變量的情況下被調用。

因此,一些像下面應該工作:

import sys 

def add_to_data(*items): 
    def decorator(func): 
     name = func.__name__ 
     data = sys._getframe(1).f_locals.get('data') 
     if data is not None: 
      data.setdefault(name, []).extend(items) 
     return func 
    return decorator 

如果你不想依賴於sys._getframe或想要的東西更清楚,你可以讓你的@add_to_data功能裝飾簡單標記與適當的功能屬性的方法,然後使用類裝飾者t o從所有標記的方法構建data字典。

+0

我沒有想到'sys._getframe()';你是對的,那會奏效。 – abarnert

+2

我在閱讀'zope.interface'源代碼時第一次看到這個技巧。這是一種技巧,裝飾者的用戶看起來非常乾淨,但其他人可能難以理解實現。 –

1

你不能那樣做,因爲類對象還不存在。

你也許可以通過創建具有@classmethod中的子類的裝飾,或與一類裝飾存儲的東西別的地方一起或裝飾用一個基類做類似的事情元類是副本的存儲到類的之後的data屬性。

嗯,真的,不知道你的實際目標是什麼 - 無論你是在Py2還是Py3上(以及你是否只關心CPython或任何Python) - 我很難知道該怎麼建議。

+0

另請參見https://stackoverflow.com/questions/3054372/auto-register-class-methods-using-decorator – mueslo