python-33 面向对象之三:静态属性、类方法、静态方法、接口、抽象类
属性:
公有属性 (属于类,每个类一份)
普通属性 (属于对象,每个对象一份)
私有属性 (属于对象,跟普通属性相似,只是不能通过对象直接访问)
方法:(按作用)
构造方法
析构函数
方法:(按类型)
普通方法(类中普通方法,自动传入self)
私有方法(方法前面加两个下划线)
静态方法(类工具包,类和对象都不绑定,都 可调用)
类方法(绑定具体的类,仅类可调用,自动传入cls)
静态属性(也是方法,只是伪装成属性,以调用属性的方法去调用,即不用加括号)
静态方法
@staticmethod
静态方法,又叫类工具包,既不绑定类,也不绑定对象,两者都可调用,
类方法
@classmethod
类方法,仅类可调用,传入的值也必须是类的公有数据属性,
就是说类方法只能操作类本身的公有字段
静态属性
@property
静态属性:将方法属性伪装成数据属性,和数据属性一样去调用
# 类的静态属性:把函数属性变成数据属性,这样进行了伪装,表面上看是数据属性,实质是函数属性,静态方法语法糖:@property a='aa' b='bb' class Room(): tag='建筑物' #类的静态属性 def __init__(self,name,long,width): self.long=long self.width=width self.name=name @property #在方法属性前加上 @property,使该方法属性变成了类的静态属性,调用方法:实例.方法名,作用:伪装成静态属性,让用户不知道其内部逻辑 def cal_area(self): print('%s房子的面积是%d'%(self.name,self.width*self.long)) def owner(self):#普通方法 print('this is %s hours'%self.name) #类方法:将方法属性只跟类绑定,与实例无关,语法糖@classmethod,在类字典中 @classmethod def tell_info(cls):#自动填入cls,即与类绑定 print('类型--->',cls.tag) #类静态方法:与类和实例都不绑定,它只是名义归属类管理,不能使用类变量和实例变量,是类的工具包,语法糖@staticmethod @staticmethod def test(a,b): #不自动填入cls和self,表明不和任何绑定,类和实例都可调用 print('%s 和 %s正在玩耍'%(a,b)) #print(self.width) 不能使用实例变量 #print(cls.tag) 也不能使用类变量 def test_1(name): print("name=%s"%name) r1=Room('xm',1,5) r2=Room('mf',30,50) r1.cal_area #变成静态属性后, r1.cal_area()变成调用属性一样r1.cal_area r2.cal_area # r2.cal_area()--》r2.cal_area Room.owner(r1)#一般方法属性,用类调用时,必需传入一个实例对象,类型---> 建筑物 Room.tell_info()#类方法,用类调用,就不用传入实例对象了,这样与实例无任何关系了 Room.test('小红','小白')#小红 和 小白正在玩耍 r1.test('小黑','小王')#小黑 和 小王正在玩耍 r2.test(a,b)#aa 和 bb正在玩耍 Room.test_1('cat')#类可以调用,对象不可以调用,但一般不这样用。 r1.test_1('小猫') #TypeError: test_1() takes 1 positional argument but 2 were given,自动传入-个self参数,but 2 were given
一、接口
接口:interface,像在java、c++中拥有的类,而在python中,没有这种接口说法,只有接口类
接口的作用:制定规范、标准
实现方法:仅管python中没有接口(interface),但可以通过抽象类来实现接口的功能。
继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能.
实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
1.做出良好的抽象类,2.规定兼容接口 3.调用者可以无需关心具体实现细节,可以一视同仁处理实现特定接口的所有对象。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
二、抽象类
什么是抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案
在python中实现抽象类
#1.接口:接口就是一个函数,在基类中利用装饰器方法,将类的方法属性实义为一个接口函数 #接口基类:是一个抽象类,只定义方法属性名,不去具体实现功能,它起到归一和制定标准的作用, # 接口类的具体功能在其继承的子类中实现, import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): #接口:抽象方法类,只定义函数名,不去具体实现功能 @abc.abstractmethod #利用装饰器,定义抽象方法 def read(self): '子类必须定义读功能' pass @abc.abstractmethod def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # t1=Txt() #报错,子类没有定义抽象方法 class Disk(All_file):#接口继承子类,必需显示继承所有方法,并根据需要实现其具体功能。 def read(self): print("硬盘读") def write(self): pass class Memro(All_file): def read(self): pass def write(self): print("内存写") d=Disk() m=Memro() #这样大家都是被归一化了,也就是一切皆文件的思想 d.read() d.write() m.read() m.write()
三、抽象类和接口类
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。
1. 多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
接口隔离原则:
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
2. 方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
多继承遍历顺序:
- 经典类:深度优先
- 新式类:广度优先
继承的作用
- 减少代码的重用
- 提高代码可读性
- 规范编程模式