У декораторов не должно быть побочных эффектов? - PullRequest
1 голос
/ 19 сентября 2009

Редактирование, потому что исходный код сбивал с толку.

Я бы предположил, что эти две вещи одинаковы,

#I would use either of these
#Option 1
def bar(*args):
    pass
foo = deco(bar)

#Option2
@deco
def foo(*args):
    pass

Однако, если у декораторов deco есть побочные эффекты, это не гарантируется. В частности, это было мое ожидание от декоратора (без побочных эффектов), и я столкнулся с одним с побочным эффектом и был укушен этим,

#Option1
def bar(*args):
    pass
foo = register.filter(bar)

#Option 2
@register.filter
def foo(val, arg):
    pass

Значит, мои ожидания неверны или Джанго несовместим с лучшими практиками?

Ответы [ 2 ]

2 голосов
/ 19 сентября 2009

На самом деле, они оба абсолютно одинаковы:

def foo(*args):
    pass
foo = deco(foo)

@deco
def foo(*args):
    pass

Если вы хотите украсить bar и назвать его foo, foo = deco(bar) - правильный путь. В нем говорится: «украсьте эту ранее определенную вещь под названием bar и назовите ее foo». Смысл синтаксиса декоратора состоит в том, чтобы указывать на функцию переноса перед определением, а не переименовывать его.

Если вам не нужно использовать bar позже, нет необходимости вызывать недекорированную функцию с другим именем. Делая это, вы теряете возможность использовать синтаксис декоратора sugar.

deco не обязательно должно быть функцией. Это может быть объект с методом __call__, который полезен именно для инкапсуляции побочных эффектов.

0 голосов
/ 19 сентября 2009

Ваши примеры не выражают одно и то же в каждом случае! Почему вы настаиваете на использовании бара?

Возьмите свой первый пример:

#Option 1
def bar(*args):
    pass
foo = deco(bar)

#Option2
@deco
def foo(*args):
    pass

Вариант 1 (буквально)

foo = deco(bar)

, но вариант 2 эквивалентен

foo = deco(foo)

Разве вы не видите разницу?

Итак, в общем, да: ваше предположение и ваши ожидания неверны.

Если вам нужна неокрашенная версия вашей функции, а также оформленная, просто сохраните ее заранее:

def foo(*args):
    pass
bar = foo
foo = deco(foo)
...