对于模块级函数,此代码包含:
def dec(f):
def wrap(*args, **kwargs):
f(*args, **kwargs)
return wrap
@dec
def foo(arg1):
pass
然而,当装饰方法时,你必须有一个参数来捕捉实例。
def dec(f):
def wrap(self, *args, **kwargs):
f(self, *args, **kwargs)
return wrap
class Test:
def __init__(self):
pass
@dec
def foo(self, arg1):
pass
为什么会这样?关于self
*args
无法捕捉它的特别之处是什么?毕竟不仅仅是另一个位置论证?
另外,它是如何(self
)传递到内部wrap
函数的?
对于第一种情况,它只相当于foo = dec(foo)
。从我通过闭包学到的知识,在foo
作为参数传递给装饰器之前。它创建了一个__closure__
的机箱,因此它可以保留传递给foo
的任何参数。
为什么当谈到方法时,显然self
似乎不是__closure__
的一部分?
答案 0 :(得分:3)
为什么会这样?
self
*args
无法捕捉到它的特别之处是什么?
这个问题是基于一个有缺陷的前提。事实上,*args
可以包括self
,无论是否有装饰器。以下两个例子说明了这一点。
没有装饰者:
class Test(object):
def foo(self, *args):
return (self,) + args
def bar(*args): # for the purposes of illustration
return args
t = Test()
print(t.foo(42))
print(t.bar(42))
有装饰者:
def dec(f):
def wrap(*args, **kwargs):
return f(*args, **kwargs)
return wrap
class Test(object):
@dec
def foo(self, arg1):
return (self, arg1)
t = Test()
print(t.foo(42))
答案 1 :(得分:0)
我认为Python本身的创造者最好说明了这一点:
http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html
主要两点是:
有一个很好的论据要求在参数列表中要求明确的“自我”强化了这两种调用方法的方法之间的理论等效性。
和
在参数列表中保持显式“self”的另一个论点是能够通过将函数戳入其中来动态修改类,从而创建相应的方法。