2015-06-19 2 views
0

Мой код очень прост. это для испытания, но я получаю большую ошибку: nonetype не отозваны:Декораторы Python Я встречаю странную ошибку

def deco(when): 
    def wrapper(fun): 
     print 'before call myfun' 
     fun() 
     print 'after call myfun' 
    return wrapper 
@deco('a') 
def fun(): 
    print 'in fun1' 
fun() 

Но когда она слегка модифицирована, ошибка удаляется:

def deco(when): 
    def wrapper(fun): 
     def dec(): 
      print 'before call myfun' 
      fun() 
      print 'after call myfun' 
     return dec 
    return wrapper 

@deco('a') 
def fun(): 
    print 'in fun' 
fun() 

Можете ли вы сказать причину? Я был совершенно смущен.

Более того, во втором кодовом блоке, как оболочка methon() может видеть переменную 'fun', переменная 'fun' не находится в контексте (arg верхнего methond 'when' вместо 'fun '), я тоже смущен.

Благодаря вашей помощи

+1

Исправьте углубление. –

ответ

0

Когда декоратор обеспечивается с аргументами, она рассматривается как «декоратора генератора», и должен вернуть правильный декоратор.

См. Также python decorators with parameters.

+0

Концепция «декоратор-генератор» очень яркая, и спасибо за вашу ссылку, она решает мою проблему –

3

декоратор это функция, которая принимает функцию и возвращает новую функцию. Это, как правило, выглядит как

def deco(fun): 
    def wrapped(*args, **kwargs): 
     # something... 
     return fun(*args, **kwargs) 
    return wrapped 

Выражение после @ должно вернуть декоратор. Если это выражение является вызовом функции, то вызываемая им функция должна вернуть декоратор. Таким образом, она должна была бы выглядеть

def deco_with_args(arg): 
    def deco(fun): # The decorator function that will be returned 
     def wrapped(*args, **kwargs): # The wrapper function that will finally be assigned to the decorated name 
      # something... 
      return fun(*args, **kwargs) 
     return wrapped 
    return deco