欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python的静态方法和类成员方法

程序员文章站 2023-11-15 12:41:46
python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的: 1)静态方法无需传入self参数,类成员方法需传入代表本类的cls参数; 2)从第...

python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的:
1)静态方法无需传入self参数,类成员方法需传入代表本类的cls参数;
2)从第1条,静态方法是无法访问实例变量的,而类成员方法也同样无法访问实例变量,但可以访问类变量;
3)静态方法有点像函数工具库的作用,而类成员方法则更接近类似java面向对象概念中的静态方法。
 
实现静态方法和类方法的两种方式
一、在python 2.3及之前,用staticmethod和classmethod类型对象包装实现
例子如下(注意print里的说明):
class myclass:
    val1 = 'value 1'
    def __init__(self):
        self.val2 = 'value 2'
    def staticmd():
        print '静态方法,无法访问val1和val2'
    smd = staticmethod(staticmd)

    def classmd(cls):
        print '类方法,类:' + str(cls) + ',val1:' + cls.val1 + ',无法访问val2的值'
    cmd = classmethod(classmd)

执行:
>>> mc = myclass()
>>> mc.smd()
>>> mc.cmd()
>>> myclass.smd()
>>> myclass.cmd()
 
二、在python 2.4及之后,用装饰器(decorators)实现
装饰器使用@操作符,例子如下:
class myclass:
    val1 = 'value 1'
    def __init__(self):
        self.val2 = 'value 2'

    @staticmethod
    def staticmd():
        print '静态方法,无法访问val1和val2'

    @classmethod
    def classmd(cls):
        print '类方法,类:' + str(cls) + ',val1:' + cls.val1 + ',无法访问val2的值'

不管是以上两种方式中的哪一种,执行情况都是一样的,以方式二执行结果为例分析如下:
执行:
>>> mc = myclass()  # 实例化

>>> mc.staticmd()  # 实例调用静态方法,无法访问实例变量val1和val2
>>>
静态方法,无法访问val1和val2
 
>>> mc.classmd()  # 实例调用类方法,注意,这里访问的是类myclass的变量val1的值,不是实例化后mc的实例变量val1,这里转印机容易混淆,往下看就会明白。val2一直是实例变量,所以无法访问
>>>
类方法,类:__main__.myclass,val1:value 1,无法访问val2的值

>>> myclass.staticmd()  # 类直接调用静态方法,结果同上面的实例调用,无论是类变量还是实例变量都无法访问
>>>
静态方法,无法访问val1和val2
 
>>> myclass.classmd()  # 类直接调用类方法,结果同上面的实例调用
>>>
类方法,类:__main__.myclass,val1:value 1,无法访问val2的值
 
>>> mc.val1 = 'value changed'  # 改变实例变量val1的值

>>> mc.classmd()  # 实例调用类方法,注意到cls.val1的值没变,所以,这时的cls.val1是类变量val1,而非实例变量val1
>>>
类方法,类:__main__.myclass,val1:value 1,无法访问val2的值

>>> myclass.classmd()  # 类直接调用类方法,结果同上面的实例调用
>>>
类方法,类:__main__.myclass,val1:value 1,无法访问val2的值
 
>>> myclass.val1 = 'class value changed'  # 改变类变量val1的值
>>> mc.classmd()  # 实例调用类方法,注意到cls.val1的值变了,所以,进一步证明了这时的cls.val1是类变量val1,而非实例变量val1
>>>
类方法,类:__main__.myclass,val1:class value changed,无法访问val2的值
 
>>> myclass.classmd()  # 类直接调用类方法,结果同上面的实例调用
>>>
类方法,类:__main__.myclass,val1:class value changed,无法访问val2的值
 
结论
如果上述执行过程太复杂,记住以下两点就好了:
静态方法:无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系,换个角度来讲,其实就是放在一个类的作用域里的函数而已。
类成员方法:可以访问类属性,无法访问实例属性。上述的变量val1,在类里是类变量,在实例中又是实例变量,所以容易混淆。