python的classmethod和staticmethod小谈

󰃭 2016-04-13

概念

python 的classmethod 与staticmethod 这两个有什么区别? 二者又有什么联系? 在google和baidu之后, 得到的大致的联系就是二者都是对类的方法的静态调用的装饰器, 即对类的方法的静态调用可以用这两种方式实现。 区别体现在classmethod 也可以用类的实例调用, 而staticmethod 则不能如此

原因

假设 class A 中 使用 classmethod 装饰函数 a, 如下:

class A():
    _info = "hello world"
    @classmethod
    def a(arg):
        print arg._info

那么对a的调用既可以直接类似静态调用

A.a()

也可以先实例化, 再调用:

aaa = A()
aaa.a()

但如果把classmethod 换成staticmehtod:

class A():
    _info = "hello world"
    @staticmethod
    def a(arg):
        print arg._info

就只能静态调用了(staticmethod 名字就已经看得出来了)

原因是, classmethod 是类(不是实例化的对象)作为第一个参数传递给了函数, 比如在第一个例子里的aaa.a()和A.a(), 都是直接将类或者对象的类(再一次, 不是实例)传递进去, 进而实现静态调用

而staticmethod 只是将函数声明为静态方法, 没有传递任何内容进去

静态变量范围

在实验过程中, 类的静态变量对类的实例产生了一些有趣的影响, 如下

class c():
    _num = 0

    def add(self,num):
        self._num += nu

    def add_c(self,num)
        c._num += num

    def get(self):
        return self._nu

    def get_c(self):
        return c._num
        
 if __name__ == "__main_
    c1 = c()
    c2 = c()

    c1.add_c(3)
    c2.add_c(2)
    c1.add(9)
    c2.add(4)
    print c1.get()#?
    print c2.get()#?
    print c1.get_c()#?
    print c2.get_c()#?

结果依次应该是什么呢,如下 14 9 5 5

让我们产生疑问的是第一个和第二个的结果怎么是14 和 9, 很明显3+2+9 = 14, 3+2+4 = 9, 是通过这两种方式的结果, 看起来就像 add_c 里的类的变量影响了 add里的类的实例。

确实如此, 对类的变量的修改会影响类的实例的变量的使用, 所以我们在通过 classname.variable 的方式对类变量做修改的时候一定要小心。

而类的实例并不会影响类的静态变量,只是会修改对象实例本身的值, 所以后面两个的结果总是5,5

同样, 如果我们使用classmethod 和staticmethod

 @staticmethod
 def get_sm():
     return c._num

 @classmethod
 def get_cm(arg):
     print arg
     return arg._num

结果也将仅仅是静态变量变化后的结果, 与类的实例无关

PS: 以上是对classmethod 和staticmethod 的暂时做的了解的总结, 如有纰漏, 请及时指正