编辑,因为初始代码令人困惑。
我认为这两件事情是一样的,
#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
我的期望是错误的,还是django与最佳做法不一致?
答案 0 :(得分:2)
实际上,这两者完全相同:
def foo(*args):
pass
foo = deco(foo)
@deco
def foo(*args):
pass
如果您要装饰bar
并将其称为foo
,foo = deco(bar)
是正确的方法。它说:“装饰这个先前定义的名为bar
的东西并称之为foo
”。装饰器语法的要点是在定义之前声明包装函数,而不是重命名它。
除非您稍后需要使用bar
,否则没有理由使用其他名称调用未修饰的函数。通过这样做,您将完全失去使用装饰器语法糖的能力。
deco
不需要是一个函数。它可以是具有__call__
方法的对象,这对于封装副作用非常有用。
答案 1 :(得分:0)
在每种情况下,您的示例都不会表达相同的内容!你为什么坚持使用吧?
拿你的第一个例子:
#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)