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 我觉得还是 ...
随机推荐
- C#实现图像拖拽以及锚点缩放功能
本文主要实现C#窗体图像拖拽以及锚点缩放功能 1.新建Windows窗体应用项目,添加一个panel控件,在panel控件上添加picturebox控件 代码如下: using System; usi ...
- 【深入学习linux】Linux系统安装
1. 配置内存大小,和设置镜像文件,开启虚拟机,点击虚拟机,立即按F2,会出现下图 2. 选择 Boot 菜单,默认是以硬盘进行启动,但是硬盘目前为空,则不能启动,需要改成以光盘形式启动即 CD-RO ...
- 虚拟机ubuntu16下cheese打开摄像头黑屏问题
在win7上安装了一个ubuntu1604的虚拟机: 在虚拟机下打开电脑上连接的摄像头时,用ubuntu16自带的cheese软件查看是黑屏: 但是cheese上有摄像头名字显示,就是打不开:如下图 ...
- CentOS 使用官方源yum安装最新nginx版本
CentOS 使用官方源yum安装最新nginx版本 1.创建nginx.repo # vi /etc/yum.repos.d/nginx.repo 2.添加内容#如果是CentOS6,文件内容如下: ...
- git冲突处理-Please move or remove them before you can merge
参考:https://www.cnblogs.com/wenlj/p/5866356.html https://my.oschina.net/lixiaoyan/blog/1821947 #### 将 ...
- Python中,我该如何切分字符串后保留分割符?
原文来源:https://stackoverflow.com/questions/2136556/in-python-how-do-i-split-a-string-and-keep-the-sepa ...
- python初级(302) 5 列表
一.复习 1.函数的创建 1) def关键字 2) 函数名及后面跟随的括号 3)冒号加上函数体 2.函数的调用 函数名及后面跟随的括号 3.带一个,二个,三个参数的函数及调用 二.列表 family ...
- python装饰器 语法糖
简介: 装饰器(Decorators)是 Python 的一个重要部分.简单地说:他们是修改其他函数的功能的函数. 比如说我们写flask,路由就是用装饰器定义的.如果写权限控制,那么权限控制一般也是 ...
- MySQL5.7修改wait_timeout参数
参考:https://blog.csdn.net/ivory_town1/article/details/77702357 1.修改参数配置文件 vi /etc/my.cnf [mysqld] wai ...
- [PHP] 浅谈 Laravel Authentication 的 guards 与 providers
从文档的简单介绍上来讲,有一些抽象. 个人感觉,对于概念上的大多数不理解主要还是来自于 文档不是讲设计思路,而是实际操作. 查看英文文档,通常来说可以给你最准确的直觉,而本地翻译一般比较字面或者带有理 ...