2016-07-13 1 views
0

Я пытаюсь изучить декораторы и преодолеть странное состояние, имея несколько декораторов для метода. У меня есть два декоратора @makeupper и @decorator_maker_with_arguments.Python - Несколько декораторов для работы с ошибкой

@decorator_maker_with_arguments демонстрирует доступ к аргументам внутри декоратора. Это отлично работает, печатая прилагаемые аргументы, но я вижу, что @makeupper неисправен. Он печатает None. Я поставил оператор печати рядом с его определением метода, чтобы увидеть, если его вызываемый и напечатанный, но никогда не печатает буквы в hello() в верхнем регистре.

Когда я прокомментирую @decorator_maker_with_arguments("swadhikar", "c") Я вижу @makeupper работает хорошо. Может кто-нибудь объяснить, что я запутываю здесь?

def makeupper(some_fun):  
    def wrapper(arg1, arg2): 
     return some_fun(arg1, arg2).upper() 
    return wrapper 

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 

    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2)    
     return wrapper 

    return my_decorator 

@decorator_maker_with_arguments("swadhikar", "c") 
@makeupper 
def hello(ar1, ar2): 
    return "Hello User!" 

Результат:

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "hello_arg1:another hello arg..." 
None 
+3

ваша функция упаковщик внутри 'decorator_maker ... на самом деле не называют декорированного функции - это то, что предназначено? –

+3

@ TonySuffolk66 хорошо - на самом деле он ничего не возвращает, поэтому 'None' ... –

+0

Код ведет себя корректно, непонятно, почему вы ожидали, что' 'Hello User!" 'Будет напечатан. После того, как вы примените внешний декоратор, 'fn' (в этот момент фактически' wrapper' из 'makeupper') не получает вызов. – jonrsharpe

ответ

1

, но я вижу @makeupper неисправно. Он печатает None

makeupper не работает с ошибкой. Внешний декоратор decorator_maker_with_arguments не звонит wrapper из makeupper.

И у вас есть None, потому что вы ничего не возвращаете от wrapper от decorator_maker_with_arguments.

Следующие модификации decorator_maker отражают предлагаемые корректировки:

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 
    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      out = fn(fn_arg1, fn_arg2) 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2) 
      return out   
     return wrapper 
    return my_decorator 

Выходных:

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "hello_arg1:another hello arg..." 
HELLO USER! 

Вы можете добавить некоторые синтаксический сахар, украшая ваши обертки с functool.wraps, но, возможно, это необходимо, по крайней мере, если вы хотите сохранить такие функции, как имена функций, докстры и т. д.

+0

Я думаю, вы могли бы сказать, что 'functool.wraps' является синтаксическим сахаром, но, возможно, это необходимо, по крайней мере, если вы хотите хранить такие вещи, как имена функций, docstrings и т. Д. –

+0

@WayneWerner Спасибо. –

1

Вы можете добавить оператор return внутри функции оболочки my_decorator.

Как следующее:

def makeupper(some_fun):  
    def wrapper(arg1, arg2): 
     return some_fun(arg1, arg2).upper() 
    return wrapper 

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 

    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2)    
      return fn(fn_arg1, fn_arg2) 
     return wrapper 

    return my_decorator 

@decorator_maker_with_arguments("swadhikar", "c") 
@makeupper 
def hello(ar1, ar2): 
    return "Hello User!" 

print hello('arg1', 'arg2') 

Выход:

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "arg1:arg2" 
HELLO USER!