十五、类函数、成员函数、静态函数、抽象函数、方法伪装属性 本篇博客是滚雪球学Python第二轮的最后一篇博客,我们将内容继续提升到面向对象部分,为你补充类里面的一些装饰器,学习之后,希望你的Python基础知识可以更上一层楼。15。1类函数classmethod 先直接看代码,再对代码内容进行分析与学习。classMyClass(object):在类定义中定义变量clsvar类变量definit(self):print(构造函数)self。x构造函数中的属于实例变量类方法,第一个参数必须默认传类,一般习惯用cls。classmethoddefclassmethod(cls):print(classmethod是类方法,类名直接调用)类方法不可以调用类内部的对象变量(实例变量)print(cls。x)类方法可以通过类名直接调用,也可以通过对象来调用即使通过实例调用类方法,Python自动传递的也是类,而不是实例MyClass。classmethod()myclassdomMyClass()通过类的对象调用myclassdom。classmethod() 首先要掌握的是类函数的定义格式,在普通函数的前面添加装饰器classmethod,该函数就会转换为类函数,同时函数的第一个参数默认是cls,该变量名可以任意,建议使用成cls,这个是程序员之间的约定。classmethoddefclassmethod(cls): 同时类函数在调用的时候,可以通过类名。的形式进行调用,也可以通过对象。的形式调用,不过这两种调用都只是将类传递到了函数内部,不存在差异。 类函数不能调用实例变量,只能调用类变量,所谓类变量就是在类中独立声明,不在任何函数中出现的变量。在上述代码中,类变量声明部分代码如下:classMyClass(object):在类定义中定义变量clsvar类变量 在Python中,大部分classmethod装饰的函数末尾都是returncls(XXX),returnXXX。new()也就是classmethod的一个主要用途是作为构造函数。15。2静态函数staticmethod 先掌握一个概念,静态函数不属于它所在的那个类,它是独立于类的一个单独函数,只是寄存在一个类名下,先建立这个基本概念,后面学起来就简单很多了。classMyClass(object):类变量clsvar类变量definit(self):在构造函数中创建变量self。var实例变量普通的对象实例函数definstancemethod(self):可以访问类变量print(self。clsvar)可以访问实例变量print(self。var)print(实例化方法)staticmethoddefstaticmethod():print(MyClass。clsvar)无法访问到实例变量print(MyClass。var)print(self。var)print(静态方法)myclassMyClass()myclass。instancemethod()通过对象访问myclass。staticmethod()类名直接访问MyClass。staticmethod() 即使修改成下述代码,也是错误的,静态函数的第一个参数不是实例对象self,或者可以理解为静态函数没有隐形参数,如需要传递参数,在参数列表中声明即可。staticmethoddefstaticmethod(self):print(MyClass。clsvar)无法访问到实例变量print(MyClass。var)print(self。var)print(静态方法) 在同一个类中,调用静态方法,使用类名。函数名()的格式。15。3类函数与静态函数在继承类中的表现 先创建一个父类,其中包含两个静态函数与一个类函数。classF(object):staticmethoddeffstatic(x):print(静态方法,有1个参数)print(ffstatic:{x})staticmethoddeffstatic1():print(静态方法,无参数)returnF。fstatic(10)classmethoddefclassmethod(cls):print(父类中的类方法)returnF。fstatic(12)fF()f。fstatic(11)f。fstatic1()f。classmethod() 再编写一个S类继承自F类:classS(F):staticmethoddeffstatic(y):print(子类中重载了父类的静态方法)print(f子类中的参数{y})classmethoddefclassmethod(cls):print(子类中的类方法)sS()s。fstatic(110)s。classmethod()S。classmethod() 测试之后,基本结论如下: 如果在子类中覆盖了父类的静态函数,那调用时使用的是子类自己的静态函数, 如果在子类中没有覆盖父类的静态函数,那调用时使用的是父类的静态函数, 类函数同样遵循该规则。 如果希望在子类中调用父类的属性或者函数,请使用父类名。的形式实现。15。4抽象函数abstractmethod 被abstractmethod装饰的函数为抽象函数,含抽象函数的类不能实例化,继承了含抽象函数的子类必须覆盖所有抽象函数装饰的方法,未被装饰的可以不重写。 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化,实现代码如下:importabcclassMyClass(abc。ABC):abc。abstractmethoddefabsmethod(self):passdefshow(self):print(普通)classM(MyClass):defabsmethod(self):print(xxx)mmM()mm。absmethod() 抽象基类中学习还需要了解元类相关知识,在第三轮滚雪球学Python中将为你展开这部分内容。15。5方法伪装属性 在Python面向对象的编码过程中,对象。属性来获取属性的值,使用对象。方法()来调用方法,通过装饰器property可以将一个方法伪装成属性,从而使用对象。方法没有括号的形式调用。代码非常简单:classMyClass(object):definit(self,name):self。namenamepropertydefname(self):returnself。namemMyClass(橡皮擦)print(m。name) 这种写法最直接的应用,就是将部分属性变成只读属性,例如,上述代码,你无法通过下述代码对name进行修改。classMyClass(object):definit(self,name):self。namenamepropertydefname(self):returnself。namemMyClass(橡皮擦)m。name擦哥擦姐print(m。name) 如果希望方法伪装的属性具备修改和删除功能,需要参考下述代码:classMyClass(object):definit(self,name):self。namenamepropertydefname(self):returnself。namename。setterdefname(self,name):self。namenamename。deleterdefname(self):delself。namemMyClass(橡皮擦)m。name擦哥擦姐print(m。name) 上述代码在将name方法伪装成属性之后,可以通过name。setter和name。deleter对同名的name方法进行装饰,从而实现了修改与删除功能。 所以一般使用方法伪装属性的步骤是:property装饰器,可以用来将类中的方法伪装成属性;方法名。setter装饰器,在修改伪装成属性的方法值时会调用它;方法名。deleter装饰器,在删除伪装成属性的方法值时会调用它。 如果你觉得这个比较麻烦,还存在一种方法伪装属性的方式。使用property函数,原型如下最后一个参数是字符串,调用实例。属性。doc时的描述信息property(fgetNone,fsetNone,fdelNone,docNone) 通过上述函数将方法伪装成属性的代码为:classMyClass(object):definit(self,name):self。namenamedefdelname(self):delself。namedefsetname(self,name):self。namenamedefgetname(self):returnself。name将方法伪装成属性nameproperty(getname,setname,delname)mMyClass(梦想橡皮擦)print(m。name)m。name橡皮擦print(m。name)delm。name15。6这篇博客的总结 滚雪球学Python第二轮15篇博客在一次结束了,下一轮将在4月中旬再次开启,学Python我们一直在路上,希望本系列的课程对你的Python学习有所助力。