2010-01-10 84 views
1

下面的代碼中的註釋是否正確?特別是「實例= ...」嗎?Python:裝飾器:下面的代碼是如何工作的?

# This does nothing. 

class donothing(object): 
    def __init__(self, func): 
     """ 
     The 'func' argument is the function being decorated because in this 
     case, we're not instantiating the decorator class. Instead we are just 
     using the class object as a callable (a class is always callable as this 
     is how an instance is returned) to use as a decorator, which means that 
     it is being instantiated upon definition of the decorated function and 
     the decorated function is being passed in as an argument to the class's 
     __init__ method. 
     """ 
     self.func = func 

    def __call__(self, *args, **kwargs): 
     """ 
     The __call__ function is called when the decorated function is called 
     because the function has be eaten by the decorator class. Now it's up to 
     the this method to return a call to the original function. The arguments 
     are passed in as args, kwargs to be manipulated. 
     """ 
     # Returns original function call with original arguments. 
     return self.func(*args, **kwargs) 

@donothing 
def printer(text): 
    print(text) 

printer('hello world') 

# The printer function is now an alias for the donothing instance created, so 
# the preceding was the same as: 
# 
# instance = donothing(printer) 
# instance('hello world') 
# 


# Next example: 

class checkforkeysinparams(object): 
    def __init__(self, required): 
     self.required = set(required) 

    def __call__(self, params): 
     def wrapper(params): 
      missing = self.required.difference(params) 
      if missing: 
       raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing))) 
     return wrapper 


# Apply decorator class, passing in the __init__'s 'required' argument. 

@checkforkeysinparams(['name', 'pass', 'code']) 
def complex_function(params): 
    # Obviously these three are needed or a KeyError will be raised. 
    print(params['name']) 
    print(params['pass']) 
    print(params['code']) 


# Create params to pass in. Note, I've commented out one of the required params. 

params = { 
    'name': 'John Doe', 
    'pass': 'OpenSesame', 
    #'code': '1134', 
} 

# This call will output: TypeError: Missing from "params" argument: code 

complex_function(params=params) 
+0

是,'instance = ...'的東西幾乎是'@ donothing'裝飾器在內部被使用的方式。 – 2010-01-10 06:27:34

+0

你可以測試它,而不是問「這是否工作?」... – 2010-01-10 08:24:49

+0

@Tor Valamo學習閱讀某個時間。這是非常自由的。我的問題是:「以下代碼如何工作?」 – orokusaki 2010-01-11 02:15:05

回答

2

是完美的描述,裝飾donothing裝飾功能printer並返回donothing類的對象,所以是裝飾簡單地歸結爲

x = donothing(func) # donothing is a class not function 

,如果你能使用它像這樣,你希望避免@deco語法。

所以現在x是一個對象,當你做X(),該對象的__call__被調用,有它調用中傳遞的功能__init__

編輯: 其次裝飾是錯誤的,因爲它只檢查了參數,但永遠不會調用傳遞 和函數的函數傳遞給裝飾器的名字params但應命名像FUNC或更好的名字

可以測試它通過傳遞正確的PARAMS

什麼都不做
params = { 
    'name': 'John Doe', 
    'pass': 'OpenSesame', 
    'code': '1134', 
} 
complex_function(params=params) 

它不打印作爲complex_function應該做的參數。

所以正確裝飾是

class checkforkeysinparams(object): 
    def __init__(self, required): 
     self.required = set(required) 

    def __call__(self, func): 
     def wrapper(params): 
      missing = self.required.difference(params) 
      if missing: 
       raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing))) 

      func(params) 

     return wrapper 

在第一示例類被用作裝飾本身,checkforkeysinparams類這裏的對象被用作deocrator 因此功能被傳遞給該對象的__call__

+0

甜的thx澄清,順便說一句,我喜歡@語法。那麼第二個呢。 – orokusaki 2010-01-10 07:01:29

+0

@orokusaki,我添加了第二個裝飾者的解釋,其中btw被錯誤編碼 – 2010-01-10 08:20:40

+0

哦,甜蜜的感謝Anurag。 – orokusaki 2010-01-11 02:13:40