2015-12-08 2 views
2

Новое для Python и попытка понять разницу между этими двумя декораторами, в которых декоратор A принимает в качестве аргумента функцию, которую он украшает, и декоратор B, кажется, передает украшенную функцию функции внутри себя.Понимание различий между этими двумя декораторами

декоратор А:

def my_decorator(some_function): 

    def wrapper(): 

     print "Something is happening before some_function() is called." 

     some_function() 

     print "Something is happening after some_function() is called." 

    return wrapper 

@ my_decorator 
def just_some_function(): 
    print "Wheee!" 

Будет производить:

Something is happening before some_function() is called. 
Wheee! 
Something is happening after some_function() is called. 
None 

декоратор Б:

def decorator_factory(enter_message, exit_message): 

    def simple_decorator(f): 
     def wrapper(): 
      print enter_message 
      f() 
      print exit_message 
     return wrapper 
    return simple_decorator 

@decorator_factory("Start", "End") 
def hello(): 
    print "Hello World" 

Будет производить:

Start 
Hello World 
End 
None 

Я понимаю, как с Decorator A, some_function() можно передать def wrapper(), потому что my_decorator() принимает some_function в качестве аргумента.

Но с Decorator B, как это, что simple_decorator(f) получает значение, возвращаемое def hello() (как f), когда decorator_factory() принимает "start" и "End" как его аргументы и не def hello()? Как Python «знает», казалось бы, автоматически передает def hello() в simple_decorator()?

+0

'@decorator_factory (...)' - вызов функции. Результат этого вызова функции затем применяется к украшенной функции;) –

ответ

1
@decorator 
def foo(): 
    ... 

ли просто синтаксический сахар для

def foo(): 
    ... 

foo = decorator(foo) 

Поэтому

@decorator_factory(...) 
def hello(): 
    ... 

эквивалентно

def hello(): 
    ... 

hello = decorator_factory(...)(hello) 

, который, конечно, эквивалентно

def hello(): 
    ... 

decorator = decorator_factory(...) 
hello = decorator(hello) 
+0

Итак, в Python возможно иметь два параметра, передавая два отдельных аргумента функции a la 'hello = decorator_factory (...) (hello)'? – AdjunctProfessorFalcon

+0

@ Malvin9000 это не два отдельных набора аргументов для одной и той же функции, а две разные функции: первый набор '(...)' передается в 'decorator_factory', который возвращает функцию, которая принимает' (hello) 'как ее аргумент. – Saksow

+1

@ Malvin9000: По аналогии давайте притворимся, что декораторы похожи на шляпы. Функции носят головные уборы. 'decorator' - это шляпа, на которую вы положили функцию. 'decorator_factory', с другой стороны, является функцией, которая создает шляпы. * Возвращаемое значение * этой функции - это шляпа, которую вы можете поместить на функцию. –

1

декоратор

@ my_decorator 
def just_some_function(): 

равна:

just_some_function = my_decorator(just_some_function) 

декоратор B

@decorator_factory("Start", "End") 
def hello(): 

равна

hello = decorator_factory("Start", "End")(hello) 

, потому что он называется один раз перед использованием, это на один шаг глубже

+0

Это должно быть 'def just_some_function() .... just_some_function = my_decorator (just_some_function)' – viraptor

2

Декоратор - это эквивалент обертывания функции, которую он украшает.

Ваш пример

@decorator_factory("Start", "End") 
def hello(): 
    print "Hello World" 

hello() 

такая же, как

def hello(): 
    print "Hello World" 

hello = decorator_factory("Start", "End")(hello) 

hello() 
+0

В Python возможно по существу передать два набора аргументов одной функции с этим: 'decorator_factory (« Старт »,« Конец ») (hello())'? – AdjunctProfessorFalcon

+0

Мой плохой о последней части, это было неправильно. – Szymon

+0

@ Malvin9000 это не два отдельных набора аргументов для одной и той же функции, а две разные функции: первый набор '(« Пуск »,« Конец »)' передается в 'decorator_factory', который возвращает функцию, которая принимает' (привет) 'в качестве аргумента. – Saksow

0

Так никто не отвечает правильно на ваш вопрос: вы хотите знать, как в декоратора В simple_decorator получает функцию f Это потому что decorator_factory возвращение, что simple_decorator функция так: decorator_factory("Start", "End")(hello) фактически эквивалентна simple_decorator(hello) (привет ваш f)

P.S. Вы можете найти ответ на свои вопросы о 2 наборах аргументов в комментариях.

Смежные вопросы