2017-08-08 58 views
4

对于模块级的功能,这样的代码保存:为什么有必要将self作为方法装饰器的参数?

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__的一部分?

+1

滑稽,如果使用在第一实施例的装饰(所以不需要重新定义分解(f)如方法级),那么它没有“自我”的呼唤,也在课堂上工作。 '@dec def foo(arg1):pass'然后将被调用为Test.foo('bar').. – Uvar

回答

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)) 
0

我认为这是最好的Python自己的创造者说:

http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html

主要的两点是:

有一个相当不错的参数做出需要明确的自我'在参数列表中加强了这两种调用方法的理论等同性。

另一种说法为在参数列表中保持显式“自我”是由戳的功能到它,这产生相应的方法动态地修改一个类的能力。

+3

呃......我其实是在问一个完全不同的问题,我可能需要重新说一下我的问题但它主要是关于装饰和封闭。 – whiteredblack

相关问题