декораторы python, вложенная функция

Я пытаюсь понять, зачем мне нужна еще одна вложенная функция при использовании декораторов. Вот пример:

 def func(f):
    def deco(*args, **kwargs):
        return f(*args, **kwargs)
    return deco

@func
def sum(a, b):
    return a+b

print sum(5, 10)

Код работает, все нормально. Но зачем мне создавать вложенную функцию «деко»? Попробуем без него:

def func(f):
    return f(*args, **kwargs)

@func
def sum(a, b):
    return a+b

print sum(5, 10)

Код не работает.

Итак, есть три вопроса:

  1. Почему второй образец не работает?
  2. Почему args, kwargs "волшебным образом" появляются, если мы используем вложенную функцию?
  3. Что я могу сделать, чтобы второй образец заработал? Разумеется, кроме вложения другой функции.

person user    schedule 06.04.2015    source источник
comment
Декоратор должен возвращать функцию, а не результат функции. В вашем первом примере он возвращает функцию ... Во втором он возвращает то, что возвращает ваша функция f.   -  person Julien Spronck    schedule 06.04.2015
comment
А как насчет 2-го и 3-го вопросов?   -  person user    schedule 06.04.2015
comment
*args и **kwargs не появляются волшебным образом, аргументы будут определены только после того, как вы вызовете свою декорированную функцию (stackoverflow.com/questions/36901/)   -  person Julien Spronck    schedule 06.04.2015
comment
Вкратце: потому что контракт для декораторов заключается в том, что они являются фабриками функций: они принимают функцию и возвращают новую функцию. Во втором примере ваш func(f) возвращает результат вызова функции. Но декоратор должен вернуть функцию (которая еще не была вызвана).   -  person Lukas Graf    schedule 06.04.2015
comment
Примечание: @func - это просто синтаксический сахар для sum = func(sum), args и kwargs, значение имеет только тогда, когда вы вызываете это новое определение sum.   -  person AChampion    schedule 06.04.2015


Ответы (1)


  1. Почему второй образец не работает?

    Поскольку вы вызываете функцию при возврате, вы не возвращаете функцию.

  2. Почему args, kwargs "волшебным образом" появляются, если мы используем вложенную функцию?

    Они не появляются волшебным образом, мы их объявляем, например:

    def deco(*args, **kwargs):
    

    Они являются общими и соответствуют любой сигнатуре функции (списку аргументов). Вам не обязательно называть их args и kwargs, это просто соглашение, вы можете называть их sharon и tracy.

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

    Ну, вы не говорите, чего ожидаете от 2-го образца. Но я думаю тогда превратить его в декоратора:

    def func(f):
        return f
    

    Но это не так уж много!

Кстати, обычно переопределять существующий встроенный Python (sum) - плохая идея - для этого у вас должна быть очень веская причина.

person cdarke    schedule 06.04.2015