十五、类函数、成员函数、静态函数、抽象函数、方法伪装属性本博客是滚雪球学习Python的在第二轮的最后一篇博客,我们会继续将内容升级到面向对象的部分,为大家补充一些类中的装饰器。学完之后,希望你的Python基础知识能更上一层楼。15.1类函数@classmethod先直接看代码,再分析学习代码内容。classMy_Class(object):#definevariableinclassdefinitioncls_var="classvariable"def__init__(self):print("constructor")self.x="instancevariableinconstructor"#class方法,不能传一个参数默认的类,一般习惯使用cls。@classmethoddefclass_method(cls):print("class_method是类方法,直接调用类名")#类方法不能调用类内部的对象变量(实例变量)#print(cls.x)#类方法可以通过类名可以直接调用,也可以通过对象调用#即使是通过实例调用类方法,Python也会自动传递类而不是实例My_Class.class_method()my_class_dom=My_Class()#通过类的对象调用my_class_dom.class_method()需要掌握的是类函数的定义格式。在普通函数前面加上装饰器@classmethod,函数就会转为类函数。同时该函数的第一个参数默认为cls。变量名可以是任意的。推荐使用Chengcls,这是程序员之间的约定。@classmethoddefclass_method(cls):同时调用类函数时,可以通过类名的形式调用。或通过对象的形式。但是,这两个调用只是将类传递给函数,没有区别。类函数不能调用实例变量,只能调用类变量。所谓类变量就是在类中独立声明,不出现在任何函数中的变量。上面代码中,类变量声明部分代码如下:classMy_Class(object):#在类定义中定义变量cls_var="classvariable"在Python中,大多数用@classmethod修饰的函数都以returncls(XXX),returnXXX.__new__()也就是说,@classmethod的主要用途之一是作为构造函数。15.2静态函数@staticmethod先掌握一个概念。静态函数不属于它所在的类。它是一个独立于类的单独函数,但它存储在一个类名下。先建立这个基本概念,后面学起来就容易多了。classMy_Class(object):#类变量cls_var="类变量"def__init__(self):#在构造函数中创建一个变量self.var="实例变量"#普通对象实例函数definstance_method(self):#可以访问classvariablesprint(self.cls_var)#可以访问实例变量print(self.var)print("Instantiationmethod")@staticmethoddefstatic_method():print(My_Class.cls_var)#不能访问实例变量#print(My_Class.var)#print(self.var)print("Staticmethod")my_class=My_Class()my_class.instance_method()#通过对象访问my_class.static_method()#类名直接访问My_Class.static_method()即使修改了下面的代码也是错误的。静态函数的第一个参数不是实例对象self,或者可以理解为静态函数没有不可见参数。如果需要传递参数,可以在参数列表中声明。@staticmethoddefstatic_method(self):print(My_Class.cls_var)#不能访问实例变量#print(My_Class.var)print(self.var)print("staticmethod")在同一个类中,调用一个静态方法,使用格式classname.functionname()。15.3继承类中类函数和静态函数的表现先创建一个父类,父类包含两个静态函数和一个类函数。classF(object):@staticmethoddeff_static(x):print("静态方法,有1个参数")print(f"f_static:{x}")@staticmethoddeff_static_1():print("静态方法,没有parameters")returnF.f_static(10)@classmethoddefclass_method(cls):print("父类中的类方法")returnF.f_static(12)f=F()f.f_static(11)f.f_static_1()f.class_method()再写一个类S继承自类F:classS(F):@staticmethoddeff_static(y):print("子类中重载了父类的静态方法")print(f"parameter{y}insubclass")@classmethoddefclass_method(cls):print("classmethodinsubclass")s=S()s.f_static(110)s.class_method()S.class_method()之后测试,基本结论如下:如果子类中覆盖了父类的静态函数,则调用时使用子类的静态函数,如果子类中没有覆盖父类的静态函数,那么调用时使用父类的静态函数时,类函数也遵循这个规则。如果要在子类中调用父类的属性或函数,请使用父类名的形式。15.4抽象函数@abstractmethod@abstractmethod修饰的函数为抽象函数,包含该抽象函数的类不能实例化,继承抽象函数的子类必须覆盖抽象函数修饰的所有方法,未修饰的不需要重写。抽象类是一个特殊的类。它的特殊之处在于只能继承,不能实例化。实现代码如下:importabcclassMy_Class(abc.ABC):@abc.abstractmethoddefabs_method(self):passdefshow(self):print("Normal")classM(My_Class):defabs_method(self):print('xxx')mm=M()mm.abs_method()抽象基类的学习也需要元类的知识,在第三轮滚雪球Python中为大家展开。15.5方法伪装属性在Python面向对象编码过程中,object.attribute用于获取属性的值,对象。method()用于调用方法。方法可以通过装饰器@property伪装成属性,从而使用object。调用时不带括号的方法。代码很简单:classMy_Class(object):def__init__(self,name):self.__name=name@propertydefname(self):returnself.__namem=My_Class("Eraser")print(m.name)这种写法最直接的应用就是把一些属性变成只读属性。例如,在上面的代码中,您不能通过下面的代码修改名称。classMy_Class(object):def__init__(self,name):self.__name=name@propertydefname(self):returnself.__namem=My_Class("Eraser")m.name="兄妹"print(m.name)如果想让方法伪装的属性具有修改和删除功能,需要参考如下代码:classMy_Class(object):def__init__(self,name):self.__name=name@propertydefname(self):returnself.__name@name.setterdefname(self,name):self.__name=name@name.deleterdefname(self):delself.__namem=My_Class("橡皮擦")m.name="BrotherWipeWipesister"print(m.name)上面代码将name方法伪装成属性后,可以使用@name.setter和@name.deleter将name方法修饰成同名,从而实现修改和删除功能。所以使用方法来伪装属性的一般步骤是:@property装饰器,可以用来将类中的方法伪装成属性;@methodname.setter装饰器,伪装成属性的方法修改值时会被调用;@method删除伪装成属性的方法值时调用的.deleter装饰器。如果你觉得这更麻烦,还有一种方法可以伪装方法的属性。使用property函数,原型如下#最后一个参数为字符串,调用实例时的描述信息.Attribute.__doc__property(fget=None,fset=None,fdel=None,doc=None)伪装成通过上面的函数作为属性的方法代码是:.__name=namedefget_name(self):returnself.__name#将方法伪装成属性name=property(get_name,set_name,del_name)m=My_Class("DreamEraser")print(m.name)m.name=《橡皮擦》print(m.name)delm.name15.6本篇博文总结雪球学习Python第二轮15篇博文一下子结束了。我们一直在学习Python的路上。希望本系列课程对大家学习Python有所帮助。
