Python 装饰师不应该有副作用吗?
正在编辑,因为初始代码令人困惑 我假设这两件事是一样的Python 装饰师不应该有副作用吗?,python,django,decorator,Python,Django,Decorator,正在编辑,因为初始代码令人困惑 我假设这两件事是一样的 #I would use either of these #Option 1 def bar(*args): pass foo = deco(bar) #Option2 @deco def foo(*args): pass 但是,如果装饰师deco有副作用,则不能保证这一点。在partcicular,这是我从一个装饰师那里得到的东西(没有副作用),我遇到了一个有副作用的,被它咬了一口 #Option1 def bar(*
#I would use either of these
#Option 1
def bar(*args):
pass
foo = deco(bar)
#Option2
@deco
def foo(*args):
pass
但是,如果装饰师deco
有副作用,则不能保证这一点。在partcicular,这是我从一个装饰师那里得到的东西(没有副作用),我遇到了一个有副作用的,被它咬了一口
#Option1
def bar(*args):
pass
foo = register.filter(bar)
#Option 2
@register.filter
def foo(val, arg):
pass
那么,我的期望是错误的,还是django与最佳实践不一致?事实上,这两者完全相同:
def foo(*args):
pass
foo = deco(foo)
@deco
def foo(*args):
pass
如果你想装饰bar
并称之为foo
,foo=deco(bar)
是正确的方法。它说:“装饰这个先前定义的东西,叫做bar
,并称之为foo
”。decorator语法的要点是在定义之前声明包装函数,而不是重命名它
除非以后需要使用bar
,否则没有理由使用其他名称调用未修饰的函数。通过这样做,您将完全失去使用decorator语法的能力
deco
不需要是函数。它可以是一个具有\uuu调用\uu
方法的对象,该方法对于精确封装副作用非常有用 您的示例并非在所有情况下都表达相同的内容!你为什么坚持使用酒吧
以你的第一个例子:
#Option 1
def bar(*args):
pass
foo = deco(bar)
#Option2
@deco
def foo(*args):
pass
选项1(字面上)有
但选项2相当于
foo = deco(foo)
你看不出有什么不同吗
总之,是的:你的假设和期望是错误的
如果您需要未修饰的函数版本以及修饰的函数版本,只需事先保存即可:
def foo(*args):
pass
bar = foo
foo = deco(foo)
@罗伯托:没错。我的问题是,它是否也应该与
foo=deco(bar)
这到底是什么bar
?Decoratordeco
包装方法foo
,并且完全等同于foo=deco(foo)
。你为什么老是问关于foo=deco(bar)
?也许你的这一误解是根本问题。bar是另一个可调用的。我想把deco(bar)的retirn值绑定到foo。下面问了一个问题,所以补充说,bar是另一个可调用的。您的示例毫无意义,因为您扔掉了您定义的foo。您将使用deco装饰foo,因此您将获得一个新的foo.hop:Ok编辑的代码,以便更好地解释问题。我以后需要访问装饰和未装饰的函数,因此需要使用选项1代码。>您为什么坚持使用bar?因为我需要访问装饰和未装饰的功能。我的假设(显然)是错误的。但为什么我认为它没有副作用是错误的?为什么你要用这样一个武断的规则限制自己?Library().register()除了注册它之外,对func还有什么作用吗?foo在前后应该是相同的…看看template/defaultfilters.py:您甚至不必使用register.filter()的返回值!
def foo(*args):
pass
bar = foo
foo = deco(foo)