一, 复习
属性的的正确存放位置: 类中应该存储所有对象公共的内容 对象中存储都是每个对象独有的(都不同)初始化函数: 给对象的属性赋初值 , 可以保证只要对象被创建就一定有相应的属性 节省了重复代码绑定方法: 指的是 将类或对象与函数进行了绑定 之所以绑定是为了提高整合度,后续在拿到对象就可以直接调用而无需关心 数据是什么 如何处理 对象也可以看做是一个存储数据的容器 对象绑定方法: 默认情况下就是绑定给对象的 当执行该方法时,需要访问对象中的内容 当使用对象调用时 会自动传入对象本身作为第一个参数 用类来调用时就是一个普通函数 该怎么传就这么传 类绑定方法: 当执行该方法时,需要访问类中的内容而不需要对象中的内容 @classmethod 无论使用类还是对象来调用都会自动传入类本身作为第一个参数 非绑定方法 既不需要访问类中的内容 也不需要访问对象中的内容 那就作为非绑定方法 就是一个普通函数 没有自动传值的效果 @staticmethod继承 说的是类与类之间的关系 存在基础关系后 子类可以直接使用父类已经存在的内容 总的来说是为了提高代码的复用性 例如猫 和狗 都属于动物类 描述的时 什么是什么的关系 如:猫是动物 要开始累积自己的类库 把经常使用的小功能写到一个模块中 以后可以直接调用 class 子类(父类): pass属性查找顺序 对象本身 -> 所在的类 -> 类的父类 -> .... object抽象 使用基础时 应该先抽象 在继承 抽象指的是 把一系列类中的相同的特征和行为抽取 形成一个新的类 (公共父类)派生 子类拥有与父类不同的内容覆盖 子类出现了与父类完全相同的名字一切皆对象 在py3里面所有东西全是对象 包括 int list 模块 函数 .....包等等.... list.append(li,1)子类访问父类的内容 1.指名道姓 直接写死了类名 即时不存在继承关系也能调用 2.super().要访问的属性 (py3出现的) 3.super(这个子类的名字,self).属性
二 , 继承已有的类来扩展新功能
#实现一个存储类,在提供基本的存取功能之外,还要可以限制存储元素的类型class MyList(list): def __init__(self,element_cls): #当你覆盖了init时,不要忘记调用super().init函数让父类完成原有的初始化操作 super().__init__() self.element_cls = element_cls def append(self,object): if object.__class__ == self.element_cls: #如果传进来的数据与我限制的的类型匹配上,则添加到列表 super().append(object) else: print('只能存储%s类型!'%self.element_cls.__name__)li = MyList(str)li.append(10) #只能存储str类型!li.append('123')print(li) #['123']
三 , 多继承问题
class A: def test(self): print('from A') super().test() #应该报错,但是执行成功了class B: def test(self): print('from B')class C(A,B): passc = C()c.test()# from A# from Bprint(C.mro()) #[, , , ]#问题:多继承时如果多个父类中出现了同名的属性/函数#你不能用眼睛去判断查找顺序,需要使用mro列表去查看真正的继承顺序#总结:super在访问父类属性时,是按照mro列表一层层往上找的class A: a = 1 passclass B(A): a = 2 passclass C(A): a = 3 passclass D(A): a = 4 passclass E(B,C,D): a = 5 passaa = E()print(aa.a)print(E.mro()) #[ , , , , , ]
四 , 组合
'''组合: 指的是一个类把另一个类作为自己的属性来使用,就称之为组合 当你定义一个类,并且这个类拥有某种类型的属性时,就称之为组合 组合描述的是:什么拥有什么的关系, 学生有书 学生有手机继承描述的是:什么是什么的关系 麦兜是猪 猪猪侠也是猪'''''class PC: def open_app(self,app_name): print('open %s'% app_name)class Student: def __init__(self,PC,notbook): self.PC = PC self.notbook = notbookpc = PC()notbook = PC()s = Student(pc,notbook)s.PC.open_app('qq')s.notbook.open_app('what')# s.PC.open_app('ch')
五 , 菱形继承
# 在py2中 A就是一个经典类# class A:# pass# 如果你的代码需要兼容py2 那应该显式的继承object 无论是直接还是间接继承class B(object): passclass A(B): pass
六 , 接口
'''接口:就是一套协议规范具体表现形式:有一堆函数,但是只明确了函数的名称,没有明确函数的具体表现'''''import abcclass USB(metaclass=abc.ABCMeta): @abc.abstractmethod def open(self): pass @abc.abstractmethod def work(self): pass @abc.abstractmethod def close(self): passclass Mouse(USB): #实现接口规定的所有功能 def open(self): print('mouse open') def work(self): print('mouse word') def close(self): print('mouse close')class KeyBord: def open(self): print('KeyBoard open') def work(self): print("KeyBoard working...") def close(self): print("KeyBoard closed") #问题是无法限制子类,必须真正的实现接口中的功能class Camera(USB): def open(self): pass def work(self): pass def close(self): passclass PC: def device(self,usb_device): usb_device.open() usb_device.work() usb_device.close()#在实例化Camera abc模块就会检查Camera是否实现了所有的抽象方法,如果没有则无法实例化c = Camera()p = PC()#创建一个鼠标设备m = Mouse()#创建一个键盘设备key1 = KeyBord()#链接到电脑上p.device(m)p.device(key1)p.device(c)
七 , 抽象
'''抽象类:具备抽象方法的类抽象方法是,没有函数体的方法抽象类的特点:不能直接实例化'''''import abcclass Test(metaclass=abc.ABCMeta): @abc.abstractmethod def say_hi(self): pass #可以有普通函数 def info(self): print('my class is Test')class TT(Test): def say_hi(self): print('i an TT obj') # passt = TT()t.info()t.say_hi()
八 , 鸭子类型
class PC(): def conntent_device(self, usb_device): usb_device.open() usb_device.work() usb_device.close()class Mouse: # 实现接口规定的所有功能 def open(self): print("mouse opened") def work(self): print("mouse working...") def close(self): print("mouse closed")mouse = Mouse()pc = PC()pc.conntent_device(mouse)class KeyBoard: def open(self): print("KeyBoard opened") def work(self): print("KeyBoard working...") def close(self): print("KeyBoard closed")key1 = KeyBoard()# 如果key1的特征和行为都像USB设备 那就把它当做USB设备来使用# 对于使用者而言可以不用关心这个对象是什么类,是如如何是实现,pc.conntent_device(key1)
class Linux: def read_data(self,device): data = device.read() return data def write_data(self,device,data): device.write(data)class Disk: def read(self): print("disk reading....") return "这是一个磁盘上的数据" def write(self,data): print("disk writing %s..." % data)class UP: def read(self): print("disk reading....") return "这是一个U盘上的数据" def write(self,data): print("disk writing %s..." % data)l = Linux()d = Disk()data = l.read_data(d)l.write_data(d,"这是一个数据....")up1 = UP()l.read_data(up1)l.write_data(up1,"一个数据...")