python静态方法和类方法 @staticmethod @classmethod

python一共有三类方法: 静态方法,类方法和实例方法。

首先看一个例子:

def foo(x):
    print "executing foo(%s)"%(x)

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

1.可以看到,实例方法需要self指向实例本身。

2.装饰器@classmethod可以创建只在类中运行而不在实例中运行的方法. 如果我们想让方法不在实例中运行,可以这样做。代码来自知乎

class Kls(object):
    no_inst = 0
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
    @classmethod
    def get_no_of_instance(cls_obj):
        return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()

这样运行的结果都是2。因为get_no_of_instance和类绑定了。

3.经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法. 比如更改环境变量或者修改其他类的属性等能用到静态方法.

静态方法放在类内部,但是不需要实际传类或者实例给方法。示例如下(来自知乎):

IND = 'ON'
class Kls(object):
    def __init__(self, data):
        self.data = data
    @staticmethod
    def checkind():
        return (IND == 'ON')
    def do_reset(self):
        if self.checkind():
            print('Reset done for:', self.data)
    def set_db(self):
        if self.checkind():
            self.db = 'New db connection'
        print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()

输出为
Reset done for: 12
DB connection made for: 12。

可以看到checkind()作为静态方法,虽然放在类内,但是不需要传入实例或者类.虽然使用self调用,但是self不会作为隐式参数传入checkkind中.而前面的实例方法和类方法会.

最后来一个综合的比较类方法,静态方法,实例方法。

也就是一开始举例的代码,实际运行结果如下:

a = A()

a.foo(13)
executing foo(<__main__.A object at 0x102f0e510>,13)

a.class_foo(13)
executing class_foo(<class '__main__.A'>,13)

a.static_foo(13)
executing static_foo(13)

A.foo()
TypeError: unbound method foo() must be called with A instance as first argument (got nothing instead)

A.class_foo(13)
executing class_foo(<class '__main__.A'>,13)

A.static_foo(13)
executing static_foo(13)

可以看到,实例方法一定需要实例才能运行,仅有类会报错,而类方法,无论使用类还是实例调用实际都是将类传给方法。静态方法不受类和对象的影响,但是二者皆可调用。可以总结为如下的表格:

 更多的可以参考stackoverflow的讨论

原文地址:https://www.cnblogs.com/sherylwang/p/5537666.html