在@classmethod中可以调用用户定义的实例方法吗?
我想在一个用@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() 本身也应该是一个实例方法。
类方法和实例方法的区别 讨论了类方法和实例方法之间的不同。