Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 装饰师不应该有副作用吗?_Python_Django_Decorator - Fatal编程技术网

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
?Decorator
deco
包装方法
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)