在同一个Python类中调用method、classmethod、staticmethod
Posted
技术标签:
【中文标题】在同一个Python类中调用method、classmethod、staticmethod【英文标题】:Calling method, classmethod, staticmethod in the same Python class 【发布时间】:2018-04-15 18:08:37 【问题描述】:从一个著名的例子中,我了解到 Python 类中方法、类方法和静态方法的区别。
来源: What is the difference between @staticmethod and @classmethod in Python?
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
# My Guesses
def My_Question(self,x):
self.foo(x)
A.class_foo(x)
A.static_foo(x)
a=A()
现在我想知道,如何在类中调用方法,@classmethod
和 @staticmethod
。
我把我的猜测放在上面的My_Question
函数中,如果我有任何错误,请纠正我。
【问题讨论】:
你所拥有的是正确的。也可以对所有 3 使用self
。
【参考方案1】:
是的,你的猜测会起作用。请注意,在类外部调用 staticmethods 和 classmethods 也是可能的/正常的:
class A():
...
A.class_foo()
A.static_foo()
还要注意在常规实例方法中,习惯上直接在实例(self
)而不是类(A
)上调用静态方法和类方法:
class A():
def instance_method(self):
self.class_foo()
self.static_foo()
这允许继承按您的预期工作——如果我从A
创建一个B
子类,如果我调用B.instance_method()
,我的class_foo
函数将得到B
而不是A
作为 cls
参数 -- 并且可能,如果我在 B
上覆盖 static_foo
以执行与 A.static_foo
略有不同的操作,这也将允许调用覆盖的版本。
一些例子可能会更清楚地说明这一点:
class A(object):
@staticmethod
def static():
print("Static, in A")
@staticmethod
def staticoverride():
print("Static, in A, overrideable")
@classmethod
def clsmethod(cls):
print("class, in A", cls)
@classmethod
def clsmethodoverrideable(cls):
print("class, in A, overridable", cls)
def instance_method(self):
self.static()
self.staticoverride()
self.clsmethod()
self.clsmethodoverride()
class B(A):
@classmethod
def clsmethodoverrideable(cls):
print("class, in B, overridable", cls)
@staticmethod
def staticoverride():
print("Static, in B, overrideable")
a = A()
b = B()
a.instance_method()
b.instance_method()
...
运行之后,尝试将instance_method
中的所有self.
更改为A.
。重新运行并比较。您会看到所有对B
的引用都已消失(即使您正在调用b.instance_method()
)。这就是为什么要使用self
而不是类的原因。
【讨论】:
我在引用帖子的最佳答案中看到,@classmethod 绑定到类,并且必须像普通类方法的“self”一样包含一个“cls”。我想知道“cls”和“self”是否有任何实际含义,所以我们必须使用这两个字符串?还有为什么不使用 cls.class_foo(x) 而不是 self.class_foo(x)? 名称self
和cls
是约定。你可以使用任何你想要的名字,但是如果你偏离了正常的约定,任何阅读你的代码的人都可能会非常大声地对你大喊大叫:-)。在classmethod
中,第一个参数是类,而在普通方法中,第一个参数是类的实例。这是您的示例代码中A
和a
之间的区别。 -- 至于“为什么不使用cls.class_foo(x)
” -- 如果你从另一个类方法调用一个类方法,你会使用它。在实例方法中,名称 cls
未定义(使用我的示例代码尝试)。【参考方案2】:
正如@wim 所说,您所拥有的是正确的。这是调用My_Question
时的输出。
>>> a.My_Question("My_Answer=D")
executing foo(<__main__.A object at 0x0000015790FF4668>,My_Answer=D)
executing class_foo(<class '__main__.A'>,My_Answer=D)
executing static_foo(My_Answer=D)
【讨论】:
以上是关于在同一个Python类中调用method、classmethod、staticmethod的主要内容,如果未能解决你的问题,请参考以下文章
Python OOP-static method,class method and instance method