2014-03-24 81 views
0

我有這樣的代碼:蟒蛇裝飾越來越函數的變量

def check_karma(needed_karma, user_karma): 
    # check karma or exit 
    return True 

def hello_world(): 
    user_karma = 50 
    check_karma(20, user_karma) 
    print "Hello World" 

我可以在這裏使用裝飾?是這樣的:

... 
@check_karma(20, user_karma) 
def hello_world(): 
    user_karma = 50 
    print "Hello World" 

我不知道我是否可以訪問內部數據該函數,因爲我成功地在測試腳本中寫了@check_karma(20)。

+0

帶參數使得裝飾沒有那麼簡單...... http://stackoverflow.com/questions/5929107/python-decorators -with-parameters – Dunno

+1

不,裝飾者不能訪問局部變量。你可以將'user_karma'作爲'hello_world()'的參數,否則你想做的事情是不可能的。 – Bakuriu

+0

'check_karam'看起來像我經常使用'assert' – cmd

回答

0

是的,在這種情況下可以使用裝飾器(它可能實際上是有利的),但是,它不像定義函數那麼簡單。在這種情況下,你想要做的是定義什麼被稱爲仿函數。 A 仿函數是一個按照函數工作的類。

例如,假設您的課程爲Apple。你可能會做實例化這個類的一個對象如下:

apple = Apple(color='red')

而現在,如果這是一個函子,你可以通過使用apple對象,就好像它是一個藉此更進一步通過使用apple()來調用它。這可以用來創建您試圖製作的裝飾器。您將初始化的check_karma類裝飾的定義,像這樣:

@check_karma(needed_karma) 
def hello_world(): 
    ... 

這是因爲一個裝飾必須是功能返回另一個函數。什麼上面的代碼片段基本上做的是這樣的:

def hello_world(): 
    ... 
hello_world = check_karma(needed_karma)(hello_world) 

,然後我們每次調用程序hello_world,我們要求的是由check_karma仿返回的功能時。應該可能從其他地方請求user_karma

這裏是一個如何應用此代碼示例:

user_karma = 50 # pretend this is where you store `user_karma`. 

class KarmaRestrictor: 
    def __init__(self, needed_karma): 
     self.needed_karma = needed_karma 

    def __call__(self, restricted_func): 
     # This is the actual decoration routine. This `__call__` descriptor 
     # is what makes this class a **functor**. 

     def _restricted_func(*args, **kwargs): 
      if self.get_user_karma() >= self.needed_karma: 
       return restricted_func(*args, **kwargs) 
      else: 
       # TODO: Maybe have a failure routine? 
       pass 

     return _restricted_func 

    def get_user_karma(self): 
     return user_karma # wherever you store this. 

check_karma = KarmaRestrictor # give this decorator an alias. 

@check_karma(20) 
def hello_world(): 
    print 'Hello World'