2014-01-20 55 views
1

我目前正在嘗試實現一個類裝飾器,它可以根據參數添加多個方法。例如:如何創建一個可以向類中添加多個方法的類裝飾器?

@decorator('my_func') 
class Screen: 
    ... 

將向測試類添加方法'my_func'(函數的主體在裝飾器中定義)。

@decorator('my_func', 'my_func2') 
class Screen: 
    ... 

將添加方法'my_func'和'my_func2'。到目前爲止,我已經成功地做到以下幾點:

def decorator(*args): 
    def wrapper(cls): 
     if not issubclass(cls, Screen): 
      raise ValueError("You can't apply this decorator " 
          "on this class.") 

     for arg in args: 
      def clicker(self): 
       return "Hey !" + arg 
      setattr(cls, arg, clicker) 
     return cls 
    return wrapper 

這裏的問題是,定義「my_func,並將」或「my_func2」指向相同的代碼,定義的最後一個(在我的例子的代碼的所有方法'my_func2')。 例如:

>>> Screen().my_func() 
"Hey ! my_func2" 
>>> Screen().my_func2() 
"Hey ! my_func2" 

我已經有很多的調整,如複製方法與函數類型,與MethodType邊界的嘗試,結果仍然總是相同的。

但是這個代碼有當裝飾被鏈接的預期行爲:

@decorator('my_func') 
@decorator('my_func2') 
class Test: 
    ... 

我的目標是當你有很多參數的使用這個裝飾,而不訴諸鏈可以是瘸子通過

歡迎任何想法!

+1

[在Python嵌套函數局部變量]的可能重複(http://stackoverflow.com/questions/12423614/local-variables-in-python-nested-functions) –

+3

你正在爲每個函數創建一個閉包,這意味着'arg'在函數被*調用*的時候被解引用,而不是在被創建的時候被引用。到那個時候'arg'已經被綁定到循環中的最後一個值。 –

+2

你可以通過'def clicker(self,arg = arg)來解決這個問題:' – thefourtheye

回答

0

感謝提供的意見,我能夠解決我的問題。正如@Martijn Pieters所描述的那樣,這個問題來自於我爲每個函數創建了一個閉包,而忽視了'arg'的範圍,因此它是循環的迭代,它是綁定這個值的。通過使「ARG」作爲一個參數,我現在可以通過我的參數在我的蓋的內壁範圍:

def decorator(*args): 
    def wrapper(cls): 
     if not issubclass(cls, Screen): 
      raise ValueError("You can't apply this decorator " 
          "on this class.") 

     for arg in args: 
      def clicker(self, marg=arg): 
       return "Hey !" + marg 
      setattr(cls, arg, clicker) 
     return cls 
    return wrapper 
相關問題