类定义内部的自我引用

6

我该如何在类定义中引用类对象?你能告诉我如何做吗?更具体地说,你如何在类方法的装饰器中传递类对象? 这里有一个简单的例子,我正在尝试将我声明的第二个方法传递给第一个方法的装饰器。

def decorate(w):
    def _wrap(f):
        def _call(*args, **kwargs):
            return w(f(*args, **kwargs))
        def _call
    return _wrap

class A():

    @dec(A.w)
    def f():
        return 2

    def w(f):
        return fr + 5 

如预期的一样,抛出了异常。

NameError: name 'A' is not defined

作为我的调查结果,我发现在decorate_wrap函数内部,globals()不包含A键,而是在_call内定义。因此,我可能可以通过字符串名称(例如@dec('A.w'))找到传递的方法,但在这种情况下,无法在_wrap闭包中缓存方法搜索。
那么如何解决这个问题呢? :)

1
在定义类时,该类尚不存在。此外,在定义f时,w不存在,因为在文件中wf之后。如果您将w移到前面,则可以通过使用@dec(w)来使其可能工作。 - BrenBarn
1
在这种情况下,就像被交给一个复杂的方程式,而在你接触纸张之前,就被要求给出精确答案。 - PurityLake
1个回答

6

在类定义期间,该类尚不存在,因此您无法这样做。

您可以在创建类后应用修饰符:

class A():
    def f(self):
        return 2

    def w(self, f):
        return fr + 5 

A.f = dec(A.w)(A.f.__func__)

或者您可以交换这两个方法的定义顺序,并仍将w视为本地名称:

class A():
    def w(self, f):
        return fr + 5 

    @dec(w)
    def f(self):
        return 2

在这两种情况下,您都需要传入一个可调用对象 A.w,该对象未绑定到实例。不会传递 self,因此您需要在装饰器中自行添加:

def decorate(w):
    def _wrap(f):
        def _call(self, *args, **kwargs):
            return w(self, f(*args, **kwargs))
        def _call
    return _wrap

如果你没有预期w被绑定(它作为静态方法),那么在这里可以使用普通的函数代替。

一般而言,创建一个装饰器来调用另一个实例中的方法有点无意义;为什么不直接从f直接调用w呢?

class A():
    def f(self):
        return self.w(2)

    def w(self, f):
        return fr + 5 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接