2010-01-11 93 views
2

現在這適用於那些新來這個問題:Python:爲什麼我無法讓我的裝飾器工作?

class ensureparams(object): 
    """ 

    Used as a decorator with an iterable passed in, this will look for each item 
    in the iterable given as a key in the params argument of the function being 
    decorated. It was built for a series of PayPal methods that require 
    different params, and AOP was the best way to handle it while staying DRY. 


    >>> @ensureparams(['name', 'pass', 'code']) 
    ... def complex_function(params): 
    ...  print(params['name']) 
    ...  print(params['pass']) 
    ...  print(params['code']) 
    >>> 
    >>> params = { 
    ...  'name': 'John Doe', 
    ...  'pass': 'OpenSesame', 
    ...  #'code': '1134', 
    ... } 
    >>> 
    >>> complex_function(params=params) 
    Traceback (most recent call last): 
     ... 
    ValueError: Missing from "params" dictionary in "complex_function": code 
    """ 
    def __init__(self, required): 
     self.required = set(required) 

    def __call__(self, func): 
     def wrapper(*args, **kwargs): 
      if not kwargs.get('params', None): 
       raise KeyError('"params" kwarg required for {0}'.format(func.__name__)) 
      missing = self.required.difference(kwargs['params']) 
      if missing: 
       raise ValueError('Missing from "params" dictionary in "{0}": {1}'.format(func.__name__, ', '.join(sorted(missing)))) 
      return func(*args, **kwargs) 
     return wrapper 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 

回答

0

我所做的是添加*指定參數時,** kwargs,只是檢查是否有通過kwargs所需的「PARAMS」參數中[「PARAMS」]經過檢查的鑰匙那kwargs params存在。

這裏的新版本(這完美的作品):

class requiresparams(object): 
    """ 

    Used as a decorator with an iterable passed in, this will look for each item 
    in the iterable given as a key in the params argument of the function being 
    decorated. It was built for a series of PayPal methods that require 
    different params, and AOP was the best way to handle it while staying DRY. 


    >>> @requiresparams(['name', 'pass', 'code']) 
    ... def complex_function(params): 
    ...  print(params['name']) 
    ...  print(params['pass']) 
    ...  print(params['code']) 
    >>> 
    >>> params = { 
    ...  'name': 'John Doe', 
    ...  'pass': 'OpenSesame', 
    ...  #'code': '1134', 
    ... } 
    >>> 
    >>> complex_function(params=params) 
    Traceback (most recent call last): 
     ... 
    ValueError: Missing from "params" dictionary: code 
    """ 
    def __init__(self, required): 
     self.required = set(required) 

    def __call__(self, func): 
     def wrapper(*args, **kwargs): 
      if not kwargs.get('params', None): 
       raise KeyError('"params" kwarg required for {0}'.format(func.__name__)) 
      missing = self.required.difference(kwargs['params']) 
      if missing: 
       raise ValueError('Missing from "params" dictionary: %s' % ', '.join(sorted(missing))) 
      return func(*args, **kwargs) 
     return wrapper 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 
2

def wrapper(params):意味着你只接受一個參數 - 這樣的過程與(self, params)調用是行不通的。你必須能夠接受一個或兩個參數,例如,至少是(如果你不需要支持呼叫W /命名參數):

def wrapper(one, two=None): 
    if two is None: params = one 
    else: params = two 
    # and the rest as above 

你可以得到更復雜/精密爲了也接受命名的論點,但這是更簡單,仍然「主要作品」;-)。

+0

哦,不,不。 'params'是字典參數的名稱。它只需要一個參數。看到包括doctest。 – orokusaki 2010-01-11 03:17:16

+0

@orokusaki,當你寫'def foo(self,params):'時,那些是** TWO **參數,而不是一個 - 計數它們。你不承認這一點是什麼導致了你的代碼中的錯誤:你**有**接受被一個或兩個參數調用,並且你的'def wrapper',被編碼,只是不(它迫使單一的論點,就像你認爲它應該......而你錯了,Python告訴你,我也是;-)。 – 2010-01-11 03:20:55

+0

你有沒有看到我的問題Alex?我如何讓裝飾器在沒有裝飾器兩個版本的情況下爲類和普通函數的方法工作。我不是一個完整的小白。我只是不明白如何爲例如方法和函數製作一個版本。 – orokusaki 2010-01-11 03:25:42

2

裝飾通常是這樣的:

def wrapper(*args, **kargs): 
    # Pull what you need out of the argument lists and do stuff with it 
    func(*args, **kargs) 

然後,他們用傳遞給他們,而不是隻用功能的參數的具體數量或特定關鍵字參數的任何功能工作。在這個特定的情況下,你可能想對傳遞給__call__的func做一些反省,看看它是一個或兩個參數函數,並確保最後一個參數被稱爲'params'。然後,只需寫wrapper這樣的:

def wrapper(*args): 
    params = args[-1] 
    missing = self.required.difference(params) 
    if missing: 
     raise ValueError('Missing from "params" argument: %s' % ', '.join(sorted(missing))) 
    func(params) 
+0

謝謝Omnifarious。我最終使用了* args,** kwargs,但是你的回答讓我想到了正確的方向。 – orokusaki 2010-01-11 03:58:45

相關問題