在@classmethod中可以调用用户定义的实例方法吗?

2 投票
3 回答
1275 浏览
提问于 2025-04-18 13:01

我想在一个用@classmethod装饰器定义的方法里面调用另一个方法,有什么办法可以做到吗?比如我有:

class A():
    def B(self):
    #do something
    return something

    @classmethod
    def C(cls):
    #do something
    x = B() #call B method
    return None

我遇到了一个错误:

NameError: global name 'B' is not defined

我可以调用B吗,还是说我也需要把B定义成类方法?

3 个回答

0

要让这个正常工作,你需要做类似下面的事情:

class A():

    def B(self):
        #do something (with self! so this requires A to be instantiated!)
        return something

    @classmethod
    def C(cls):
        #do something
        return cls().B() #instantiate class, call B method, and return results 
0

类方法是指那些不需要实例数据的方法。如果B需要实例数据,也就是用到了self,那么A就不应该是一个类方法。如果B不需要实例数据,你可以把它定义为类方法,并通过cls.B()来调用它。

1

这里的问题不是你的函数是“用户定义”的,而是“x=B()”并不是在你的类里面调用一个叫“B”的方法,而是在全局范围内调用了一个叫“B”的方法。

为了说明发生了什么,看看这段代码:

B="1"

class A():
    B="2"

    def myfunc(cls):
        print B

a = A()
a.myfunc()

如果你运行这段代码,你会看到输出是 1

如果你把 print 语句改成 print A.B,你会得到 2

在你的情况下,你需要调用 A.B(),而不是简单地调用 B()

不过,正如其他人所指出的,B() 是一个实例方法。它期望第一个传入的参数是这个类的一个实例。根据 B 的功能,你可能会遇到问题,因为你没有实例可以传给它。你可以通过传递其他对象(比如类本身)或者创建一个新的对象来解决这个问题;但在我看来,如果 C() 需要调用一个实例方法,C() 本身也应该是一个实例方法。

类方法和实例方法的区别 讨论了类方法和实例方法之间的不同。

撰写回答