撩课-Python大数据+人工智能1
撩课-Python大数据+人工智能2
撩课-Python大数据+人工智能3
撩课-Python大数据+人工智能4
撩课-Python大数据+人工智能5
撩课-Python大数据+人工智能6
撩课-Python-GUI编程-PyQt5
概念
将一些属性和相关方法封装在一个对象中
对外隐藏内部具体实现细节
内部实现, 外界不需要关心
外界只需要根据"内部提供的接口"去使用就可以
好处
1. 使用起来更加方便
因为已经把很多相关的功能, 封装成一个整体
类似于像外界提供一个工具箱
针对于不同的场景, 使用不同的工具箱就可以
2. 保证数据的安全
针对于安全级别高的数据, 可以设置成"私有";
可以控制数据为只读
外界无法修改
也可以拦截数据的写操作
进行数据校验和过滤
3. 利于代码维护
如果后期, 功能代码需要维护, 则直接修改这个类内部代码即可;
只要保证接口名称不变; 外界不需要做任何代码修改
概念
现实中的"继承"
子女继承父母的"财产资源"
编程中的"继承"
一个类"拥有"另外一个类的"资源"的方式之一
"拥有"
并不是资源的复制, 变成双份资源
而是, 资源的"使用权"
"资源"
指"非私有的"属性和方法
Dog类继承自Animal类
Dog
子类
派生类
Animal
父类
基类
超类
目的
方便资源重用
分类
单继承
概念
仅仅继承了一个父类
语法
class Dog(Animal):
pass
多继承
概念
继承了多个父类
语法
class child(Father, Mather):
pass
type和object区分
type和object
新式类和经典类
新式类
直接或者间接继承自object的类
经典类
没有直接或者间接继承自object的类
继承下的影响
资源的继承
明确
在Python中, 继承是指, 资源的使用权
所以, 测试某个资源能否被继承, 其实就是测试在子类当中, 能不能访问到父类当中的这个资源
结论
除下私有的属性和私有的方法, 其他的基本都能继承
公有属性/方法
受保护属性/方法
内置方法
资源的使用
1. 继承的几种形态
单继承链
一个子类只有一个父类
图示
无重叠的多继承链
继承链无交叉, 无公共父类
图示
有重叠的多继承链
继承链有交叉, 有公共父类
图示
2. 几种形态应该遵循的标准原则
单继承
遵循"从下到上的原则"
自己身上没有这个资源, 就到父类里面去找, 父类里面没有再往上找
无重叠的多继承
遵循"单调原则"
按照继承的先后顺序, 优先调用左侧继承链上的资源
有重叠的多继承
遵循"从下到上的原则"
简单理解就是
A继承B继承C
B重写了C类的方法, 那么A优先使用B类的方法
3. 针对于几种标准原则的方案演化
Python2.2之前
仅仅存在经典类
MRO原则
深度优先(从左往右)
问题
"有重叠的多继承"中, 违背"重写可用原则"
Python2.2
产生了新式类
MRO原则
经典类
深度优先(从左到右)
新式类
在深度优先(从左到右)的算法基础之上, 优化了一部分
如果产生重复元素, 会保留最后一个
并且, 更尊重基类出现的先后顺序
注意:
并不是"广度优先算法"
问题
无法检测出有问题的继承
有可能还会违背"局部优先"的原则
子类继承多个父类
如果子类没有, 应按照父类从左到右的顺序, 优先查找
例如
图示
按照"上述算法", 计算结果为
A -> C -> B -> D -> object
问题是: A继承 (B, C)
A中没有, 应该优先选择左侧的B呀
Python2.3-2.7
新式类经典类并存
MRO原则
经典类
深度优先(从左到右)
新式类
C3算法
Python3.x之后
MRO原则
新式类
C3算法
概念补充
MRO
MRO(Method Resolution Order)
方法解析顺序
深度优先
沿着一个继承链, 尽可能的往深了去找
具体算法步骤
1. 把根节点压入栈中
2. 每次从栈中弹出一个元素,搜索所有在它下一级的元素
把这些元素压入栈中
发现已经被处理, 则略过
3. 重复第2个步骤到结束为止
广度优先
沿着继承链, 尽可能往宽了去找
具体算法步骤
把根节点放到队列的末尾
每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾
发现已经被处理, 则略过
重复上面步骤
C3算法
真正步骤
两个公式
L(object) = [object]
L(子类(父类1, 父类2)) = [子类] + merge(L(父类1), L(父类2) , [父类1, 父类2])
注意
+ 代表合并列表
merge算法
1. 第一个列表的第一个元素
是后续列表的第一个元素
或者
后续列表中没有再次出现
则将这个元素合并到最终的解析列表中
并从当前操作的所有列表中删除
2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则
3. 如果最终无法把所有元素归并到解析列表, 则报错
类似拓扑排序, 但并不是! 切记
具体算法步骤
选择一个入度为0的顶点并输出之;
从网中删除此顶点及所有出边。
资源的覆盖
包括
属性的覆盖
方法重写
原理
在MRO的资源检索链当中
优先级比较高的类写了一个和优先级比较低的类一样的一个资源(属性或方法)
到时候, 再去获取相关资源, 就会优先选择优先级比较高的资源;
而摒弃优先级比较低的资源; 造成"覆盖"的假象
注意事项
当调用优先级比较高的资源时, 注意self的变化
资源的累加
概念
在一个类的基础之上, 增加一些额外的资源
子类相比于父类, 多一些自己特有的资源
直接增加就好
在被覆盖的方法基础之上, 新增内容
方案1
在高优先级类的方法中, 通过"类名"调用低优先级类的方法
弊端
代码维护性差
容易产生重复调用
方案2
在低优先级类的方法中, 通过"super"调用高优先级类的方法
概念
是一个类
只有在新式类中有效
作用
起着代理的作用, 帮我们完成以下任务
沿着MRO链条, 找到下一级节点, 去调用对应的方法
问题
沿着谁的MRO链条?
找谁的下一个节点?
如何应对类方法, 静态方法以及实例方法的传参问题?
语法原理
super(参数1[, 参数2])
工作原理
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
问题解决
沿着谁的MRO链条?
参数2
找谁的下一个节点?
参数1
如何应对类方法, 静态方法以及实例方法的传参问题?
使用参数2进行调用
常用具体语法形式
super(type, obj) -> bound super object;
requires isinstance(obj, type)
super(type, type2) -> bound super object;
requires issubclass(type2, type)
super()
Python3+
Python2.2+
注意
super 和父类(超类)没有实质性的关联
仅仅是沿着MRO链条, 找到下一级节点
保证调用形式的统一
要是类名调用, 全是类名调用
要是super调用, 全是super调用
多态
一个类, 所延伸的多种形态
在继承的前提下; 使用不同的子类, 调用父类的同一个方法, 产生不同的功能
调用时的多种形态
多态在Python中的体现
鸭子类型
动态类型的一种风格
只要一个对象, 会走, 会游泳, 会叫; 那它就可以当做一个鸭子进行处理
关注点在于对象的"行为和属性"; 而非对象的"类型"
多态-强调
多态的理解
补充
抽象类, 抽象方法