一, 复习
属性的的正确存放位置: 类中应该存储所有对象公共的内容 对象中存储都是每个对象独有的(都不同) 初始化函数: 给对象的属性赋初值 , 可以保证只要对象被创建就一定有相应的属性 节省了重复代码 绑定方法: 指的是 将类或对象与函数进行了绑定 之所以绑定是为了提高整合度,后续在拿到对象就可以直接调用而无需关心 数据是什么 如何处理 对象也可以看做是一个存储数据的容器 对象绑定方法: 默认情况下就是绑定给对象的 当执行该方法时,需要访问对象中的内容 当使用对象调用时 会自动传入对象本身作为第一个参数 用类来调用时就是一个普通函数 该怎么传就这么传 类绑定方法: 当执行该方法时,需要访问类中的内容而不需要对象中的内容 @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): pass c = C() c.test() # from A # from B print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] #问题:多继承时如果多个父类中出现了同名的属性/函数 #你不能用眼睛去判断查找顺序,需要使用mro列表去查看真正的继承顺序 #总结:super在访问父类属性时,是按照mro列表一层层往上找的 class A: a = 1 pass class B(A): a = 2 pass class C(A): a = 3 pass class D(A): a = 4 pass class E(B,C,D): a = 5 pass aa = E() print(aa.a) print(E.mro()) #[<class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
四 , 组合
''' 组合: 指的是一个类把另一个类作为自己的属性来使用,就称之为组合 当你定义一个类,并且这个类拥有某种类型的属性时,就称之为组合 组合描述的是:什么拥有什么的关系, 学生有书 学生有手机 继承描述的是:什么是什么的关系 麦兜是猪 猪猪侠也是猪 ''''' 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 = notbook pc = 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): pass class A(B): pass
六 , 接口
''' 接口:就是一套协议规范 具体表现形式:有一堆函数,但是只明确了函数的名称,没有明确函数的具体表现 ''''' import abc class USB(metaclass=abc.ABCMeta): @abc.abstractmethod def open(self): pass @abc.abstractmethod def work(self): pass @abc.abstractmethod def close(self): pass class 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): pass class 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 abc class 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') # pass t = 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,"一个数据...")