在同一个python类中调用方法、classmethod、staticmethod

Calling method, classmethod, staticmethod in the same Python class

从一个著名的例子中,我学到了Python类中方法、类方法和静态方法之间的区别。

Source:
What is the difference between @staticmethod and @classmethod in Python?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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函数中,如果我有任何错误,请纠正我。


是的,你的猜测会奏效的。注意,在类外部调用StaticMethods和ClassMethods也是可能的/正常的:

1
2
3
4
5
class A():
    ...

A.class_foo()
A.static_foo()

还要注意,在常规实例方法中,通常直接调用实例(self上的staticmethods和class方法,而不是类(A上的staticmethods和class方法):

1
2
3
4
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来做一些与ed稍有不同的事情OCX1〔12〕,这将允许调用重写的版本。

一些例子可能更清楚地说明了这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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()

运行之后,尝试将self.中的所有A.更改为instance_method。重新运行并比较。你会看到所有对B的引用都消失了(即使你打电话给B.instance_method())。这就是为什么您要使用self而不是类的原因。


正如@wim所说,你拥有的是正确的。这是调用My_Question时的输出。

1
2
3
4
>>> 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)