2015-08-24 2 views
2

Я только начинаю с Python, и я только что был выставлен декораторам. Я написал следующий код, имитируя то, что я вижу, и она работает:@ decorators в Python: почему внутренняя определенная функция?

def decorator_function(passed_function): 
    def inner_decorator(): 
     print('this happens before') 
     passed_function() 
     print('this happens after') 
    return inner_decorator 

@decorator_function 
def what_we_call(): 
    print('The actual function we called.') 

what_we_call() 

Но тогда я писал, что бросает ошибку:

def decorator_function(passed_function): 
    print('this happens before') 
    passed_function() 
    print('this happens after') 

@decorator_function 
def what_we_call(): 
    print('The actual function we called.') 

what_we_call() 

Так почему же мы должны иметь, что внутренний вложенная функция внутри функции декоратора? Какой цели это служит? Разве не проще было бы просто использовать синтаксис второго? Что я не получу?

Самое смешное, что они оба имеют один и тот же (правильный) выход, но второй на есть текст сообщения об ошибке, а также, говоря «TypeError: объект„NoneType“не вызываемая»

Пожалуйста, используйте язык и примеры пригодных для кого-то, начинающего с Python, его первого языка программирования, а также нового для ООП! :) Благодаря.

ответ

5

Причина заключается в том, что, когда вы заключаете what_we_call в decorator_function, выполнив:

@decorator_function 
def what_we_call(): 
    ... 

Что вы делаете:

what_we_call = decorator_function(what_we_call) 

В первом примере вас это работает, потому что вы не участвуете внутренняя_функция, вы только инициализируете ее, а затем возвращаете новую внутреннюю функцию назад (которую вы вызовете позже, когда позвоните в украшенный what_we_call):

def decorator_function(passed_function): 
    def inner_decorator(): 
     print('this happens before') 
     passed_function() 
     print('this happens after') 
    return inner_decorator 

Противоположно, в вашем втором примере вы собираетесь запустить 2 заявления печати и passed_function (what_we_call в нашем случае) в возрасте:

def decorator_function(passed_function): 
    print('this happens before') 
    passed_function() 
    print('this happens after') 

Другими словами, вы не возвращают функцию пример перед:

what_we_call = decorator_function(what_we_call) 

вы запустите код (и вы видите выход), но затем decorator_function возвращает «None» в what_we_call (перезапись первоначальную функцию), и когда вы называете «None», как если бы была функцией, на которую жалуется Python.

+0

Таким образом, decorator_function - это просто «движок», который вызывается всякий раз, когда вызывается what_we_cal(), но inner_decorator - это фактическая функция, которая возвращается обратно? Так что я мог бы вернуть все через возвращение, если это функция? – Sindyr

+0

PS: Как мне отформатировать блок кода в комментарии? – Sindyr

+0

Итак, вы могли бы даже написать это: 'def decorator_function (pass_function): return other_function' и эллипс полностью украшена, да? – Sindyr

3

Декораторы Python в основном просто синтаксический сахар. Это:

@decorator 
def fn(arg1, arg2): 
    return arg1 + arg2 

Становится это:

def fn(arg1, arg2): 
    return arg1 + arg2 
fn = decorator(fn) 

То есть, декоратор в основном принимает функцию в качестве аргумента и возвращает "что-то"; что «что-то» связано с именем украшенной функции.

Почти во всех случаях это «что-то» должно быть другой функцией, потому что ожидается, что fn будет функцией (и, вероятно, будет вызвана, как если бы это было).

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