Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)
Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)
一丶封装 , 多态
封装:
将一些东西封装到一个地方,你还可以取出来(把一些内容装到某个容器内,用到这些内容还能取出来)
类设置静态属性, 设置一些方法 或者 对象, 对象可以在其对象封装一些属性
多态:
python默认支持多态, 多态指的是一种事务具有多种形态
多态的优点:
1.多态可以增加代码的灵活度;
2.以继承和重写父类方法为前提;
3.是调用方法的技巧,不会影响到类的内部设计
个人理解: 接口(存放功能相类似的函数)重用,一种接口多种实现(通过接口调用相对应的函数)
#### 例1:
#序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系
#str,list,tuple都是序列类型
s=str('hello')
l=list([1,2,3])
t=tuple((4,5,6))
#我们可以在不考虑三者类型的前提下使用s,l,t
s.__len__() # 三者的序列类型 都有__len_()方法,
l.__len__()
t.__len__()
len(s) # len函数就具有多种形态
len(l)
len(t)
# 解释: len函数就是一种事务, 元组,列表,字符就是多种形态.因为它们三者都含有__len__()函数
#### 例2:
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass
class People(Animal): #动物的形态之一:人
def talk(self):
print('say hello')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('say aoao')
peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()
鸭子模型:是动态类型的一种风格
定义:
当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子.
概念:
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。(摘自CSDN juunny,仅供参考)
class A:
def login(self):
pass
def register(self):
pass
class B:
def login(self):
pass
def register(self):
pass
# A,B两个类,没有任何关系,独立两个,但是里面的功能相似,所以python一般会将类似于A,B两个类
# 里面的相似的功能让其命名相同.
# A,B虽然无关系,但是很默契的制定了一个规范.让你使用起来更方便.
## 个人理解:
#你可以定义一个公共的接口, 简化代码 .牛逼人都这么干
def func(obj):
obj.register()
obj.login()
一篇详细的多态文章
二丶类的约束
归一化设计:
统一接口
### pay函数就作为 统一的接口 不论用哪个平台调用都是使用pay函数
class QQ(Payment):
def pay(self,money):
print(f'支付了 {money}')
class Ali(Payment):
def pay(self,money):
print(f'支付了 {money}')
class WeChat(Payment):
def fuqian(self,money):
print(f'支付了 {money}')
# 定义接口函数
def pay(obj,money):
obj.pay(money)
q=QQ() # 实例化对象
a=Ali()
w=WeChat()
pay(q,200) # 调用接口 实现功能
pay(a,100)
pay(w,1200)
父类建立一种约束
### 父类的约束不是强制性的,不重写父类的 pay函数 也可以调用子类本身的函数,完成支付功能
class Payment:
def pay(self,money):
raise Exception('子类必须继承父类pay方法') # 当子类执行接口函数时,调用函数名与父类不一致,父类pay函数主动抛出一个异常
class QQ(Payment):
def pay(self,money):
print(f'支付了 {money}')
class Ali(Payment):
def pay(self,money):
print(f'支付了 {money}')
class WeChat(Payment):
def fuqian(self,money):
print(f'支付了 {money}')
# 定义接口
def pay(obj,money):
obj.pay(money)
q=QQ() # 实例化对象
a=Ali()
w=WeChat()
pay(q,200)
pay(a,100)
pay(w,1200) # 由于 子类没有重写父类的pay方法, 父类会主动抛出一个异常
模拟抽象类(指定一种规范)的概念,建立一种约束.
### 强制性约束, 必须重写父类的方法
from abc import abstractmethod, ABCMeta # 导入抽象类 和 抽象元类
class Payment(metaclass=ABCMeta): # 定义这个类是一个抽象类
@abstractmethod # 给父类的 pay 函数添加抽象方法装饰器. 当子类没有重写父类方法,实例化对象时,就会报错
def pay(self, money):
pass
class QQ(Payment):
def pay(self, money):
print(f'支付了 {money}')
class Ali(Payment):
def pay(self, money):
print(f'支付了 {money}')
class WeChat(Payment):
def fuqian(self, money):
print(f'支付了 {money}')
# 重写父类的pay函数,就不会报错. 不重写就会报错
def pay(self, money):
pass
# 定义接口
def pay(obj, money):
obj.pay(money)
q=QQ()
a=Ali()
w=WeChat() # 1. 实例化对象时, 就会报错. 必须重写父类的pay函数 ,
pay(q,200)
pay(a,100)
pay(w,1200)
# 由于抽象方法引自与Java的抽象类. so 原理相同
### 抽象类 不能被实例化 ,只能被继承
aa=Payment()
# TypeError: Can't instantiate abstract class Payment with abstract methods pay
三丶super的深入理解
### super() 并不是 执行父类的方法
# 单继承: super() 肯定执行父类的方法
# 多继承: super(S,self)严格按照self(就是当前对象) 从属于类的mro的执行顺序,执行 S类的下一位
class A:
def f1(self):
print('in A')
class Foo(A):
def f1(self):
super(Foo,self).f1()
print('in Foo') # 2 按照继承顺序来执行,主动执行当前类的下一个类(按照继承顺序执行) , 执行Bar类
class Bar(A):
def f1(self):
print('in Bar') # 1 按照继承顺序来执行, 执行当前类的下一个类(按照继承顺序执行),已经定位到当前的Bar中的f1函数,就不再向上寻找.
class Info(Foo,Bar):
def f1(self):
super(Info,self).f1() # 从Info当前类开始 ,执行当前类的下一个类(按照继承顺序执行), 执行Foo类, 不写是默认从Info当前类super(Info,self).f1()=super().f1()
print('in Info f1') # 按照继承顺序来执行完毕后, 再执行Info
obj = Info()
print(Info.mro()) # obj对象的 继承顺序[Info, Foo, Bar, A]
obj.f1()
# 结果: in Bar, in Foo , in Info f1
####多继承 , super指定继承哪个类,就从这个类的下一个类执行
class A:
def f1(self):
print('in A')
class Foo(A):
def f1(self):
super().f1()
print('in Foo')
class Bar(A):
def f1(self): # self = obj
print('in Bar')
class Info(Foo,Bar):
def f1(self): # self = obj
super(Foo,self).f1() # 这里指定从Foo类继承. 按照多继承规则,会执行下一个类,也就是Bar
print('in Info f1')
obj = Info()
obj.f1() # obj对象的 继承顺序[Info, Foo, Bar, A]
# 结果 : in Bar, in Info f1
Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)的更多相关文章
- Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)
Python进阶(十五)----面向对象之~继承 一丶面向对象的三大特性:封装,继承,多态 二丶什么是继承 # 什么是继承 # b 继承 a ,b是a的子类 派生类 , a是b的超类 基类 父类 # ...
- python学习day19 面向对象(一)封装/多态/继承
面向对象 封装思想:将同一类的函数函数封装到同一个py文件中,方便调用 面向对象也有封装的作用,将同一类的函数封装到一个类中 多态(鸭子模型):多种类型/多种形态 #,什么事鸭子模型 对于一个函数,p ...
- J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用
J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用 spring 中获得由spring所配置的hibernate的操作对象,然后利用此对象进行,保存,修 ...
- Python进阶(十四)----空间角度研究类,类与类之间的关系
Python进阶(十四)----空间角度研究类,类与类之间的关系 一丶从空间角度研究类 对象操作对象属性 class A(): address = '沙河' def __init__(self, na ...
- Python进阶(十二)----re模块
Python进阶(十二)----re模块 一丶re模块 re模块是python将正则表达式封装之后的一个模块.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. #正则表达式: ...
- Python进阶(十)----软件开发规范, time模块, datatime模块,random模块,collection模块(python额外数据类型)
Python进阶(十)----软件开发规范, time模块, datatime模块,random模块,collection模块(python额外数据类型) 一丶软件开发规范 六个目录: #### 对某 ...
- Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery
PyQuery:一个类似jquery的python库 学习一时爽,一直学习一直爽 Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 BeautifulSoup 美味 ...
- Python 爬虫十六式 - 第七式:正则的艺术
RE:用匹配来演绎编程的艺术 学习一时爽,一直学习一直爽 Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 pyquery 今天我们将迎来我们数据匹配部分的最后一位 ...
- Python 爬虫十六式 - 第五式:BeautifulSoup-美味的汤
BeautifulSoup 美味的汤 学习一时爽,一直学习一直爽! Hello,大家好,我是Connor,一个从无到有的技术小白.上一次我们说到了 Xpath 的使用方法.Xpath 我觉得还是 ...
随机推荐
- dd命令笔记
dd命令 用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换 参数 if=FILE 指定输入源文件, 缺省为标准输入, < if=input file > iflag=FLAGS 指 ...
- GEOS/GDAL 交叉编译ARM64-linux版本
目录 安装编译环境 编译PROJ.4 编译GEOS 编译GDAL 编译后程序运行注意事项 因为试用华为云ARM64服务器(CentOS 7 操作系统)的时候,在云服务器上编译GDAL很长时间也没有编译 ...
- flutter、rn、uni-app比较
前言 每当我们评估新技术时要问的第一个问题就是“它会给我们的业务和客户带来哪些价值?”,工程师们很容易对闪闪发光的新事物着迷,却经常会忽略这些新事物其实可能对我们的客户没有任何好处,反而只会让现有的工 ...
- Java基础 awt Frame 窗体在屏幕的中间显示
JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code ...
- docker 运行 sqlserver
docker 运行 sqlserver docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=sa123456' -e 'MSSQL_PID=Deve ...
- LeetCode 257. Binary Tree Paths(二叉树根到叶子的全部路径)
Given a binary tree, return all root-to-leaf paths. Note: A leaf is a node with no children. Example ...
- 阶段一-01.万丈高楼,地基首要-第3章 用户登录注册模块开发-3-8 优化Swagger2显示
左侧的全是英文 忽略api 把HelloController也忽略掉 重启api的服务,刷新页面.只剩下了passport的Controller 给passport接口加上注解. 重启服务,并刷新页面 ...
- 在 Windows 中配置Maven
访问http://maven.apache.org/ 点击左侧的导航栏,Download 跳转到下载maven的页面,往下滚动,看到 Files 处,选择apache-maven-3.3.9-bin- ...
- vue-cli3项目关闭烦人的代码检测
参考博客:https://blog.csdn.net/e1172090224/article/details/99636767 vue.config.js module.exports = { lin ...
- nginx使用与配置入门指南
这是一篇关于nginx使用与配置的入门指南,但不包括nginx的编译与安装.我假定你知晓如何安装nginx.对大多数Linux系统来说,nginx都已经存在于它们的软件包里,直接使用系统提供的软件管理 ...