21day学通python_铁乐学python_day21_面向对象编程3
抽象类和接口类
以下内容大部分摘自博客http://www.cnblogs.com/Eva-J/
继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,
接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,
子类继承接口类,并且实现接口中的功能。
实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,
使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕。
(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,
然后做出针对性的设计:细致到什么程度,视需求而定)。
题外话:关于java
java也是一个面向对象的编程语言,但java中不能多继承。
java程序员中有两本很好的黑皮书:
设计模式 程序设计,具有里程碑意义的设计方式,从java中演变出来的
例:单例模式----一个类只有一个实例
算法导论 计算的方法,时间和空间的问题,权威通用
由此有一些编程原则和设计模式对于python编程都是有借鉴作用的。
python编程原则
开放封闭原则
开放 对扩展是开放的
封闭 对修改是封闭的
依赖倒置原则
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程
接口隔离原则
(已经写完并交付的程序代码一般是不允许修改的。)
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
支付功能的例子
支付宝支付
qq支付
apply_pay
微信支付
class Alipay:
'''
支付宝支付
'''
def pay(self,money):
print('支付宝支付了%s元'%money)
class Applepay:
'''
apple pay支付
'''
def pay(self,money):
print('apple pay支付了%s元'%money)
class Wechatpay:
def fuqian(self,money):
'''
实现了pay的功能,但是名字不一样
'''
print('微信支付了%s元'%money)
def pay(payment,money):
'''
支付函数,总体负责支付
对应支付的对象和要支付的金额
'''
payment.pay(money)
p = Wechatpay()
pay(p,200)
#执行会报错
AttributeError: 'Wechatpay' object has no attribute 'pay'
使用ABC模块创建一个规范
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):pass # 抽象方法
class Alipay(Payment):
def pay(self,money):
print('使用支付宝支付了%s元'%money)
class QQpay(Payment):
def pay(self,money):
print('使用qq支付了%s元'%money)
class Wechatpay(Payment):
def pay(self,money):
print('使用微信支付了%s元'%money)
def recharge(self):pass
def pay(a,money):
a.pay(money) # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能
a = Alipay()
a.pay(100)
pay(a,100)
q = QQpay()
# q.pay(100)
pay(q,100)
w = Wechatpay()
pay(w,100)
抽象类和接口类做的事情 :建立规范
制定一个类的metaclass是ABCMeta,
那么这个类就变成了一个抽象类(接口类)
这个类的主要功能就是建立一个规范。
抽象类中所有被abstractmethod装饰的方法都必须被继承的子类实现
如果不实现,那么在实例化阶段将会报错
无论是抽象类还是接口类metaclass=ABCMeta 都不可以被实例化
p = Payment() # 报错
什么是抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的。
例:在python中实现抽象类
# 模拟linux一切皆文件
import abc #利用abc模块实现抽象类
class All_file(metaclass=abc.ABCMeta):
all_type='file'
@abc.abstractmethod #定义抽象方法,无需实现功能
def read(self):
'子类必须定义读功能'
pass
@abc.abstractmethod #定义抽象方法,无需实现功能
def write(self):
'子类必须定义写功能'
pass
# class Txt(All_file):
# pass
#
# t1=Txt() #报错,子类没有定义抽象方法
class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('文本数据的读取方法')
def write(self):
print('文本数据的读取方法')
class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('硬盘数据的读取方法')
def write(self):
print('硬盘数据的读取方法')
class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('进程数据的读取方法')
def write(self):
print('进程数据的读取方法')
wenbenwenjian=Txt()
yingpanwenjian=Sata()
jinchengwenjian=Process()
#这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()
print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
什么叫接口
python里没有接口的概念,那接口是哪儿来的概念呢?
从java里来的,java类没有多继承,接口可以实现多继承。
例:描述动物园
会游泳的 会走路的 会爬树的 会飞的
老虎
青蛙
天鹅
猴子
from abc import ABCMeta,abstractmethod
class FlyAnimal(metaclass=ABCMeta):
@abstractmethod
def fly(self):pass
@abstractmethod
def cal_flying_speed(self):pass
@abstractmethod
def cal_flying_height(self):pass
class WalkAnimal(metaclass=ABCMeta):
@abstractmethod
def walk(self):pass
class SwimAnimal(metaclass=ABCMeta):
@abstractmethod
def walk(self):pass
class Tiger(WalkAnimal,SwimAnimal):
def walk(self):pass
def swim(self):pass
class Monkey:
def walk(self):pass
def climb(self):pass
class Swan(FlyAnimal,WalkAnimal,SwimAnimal):
def swim(self):pass
def walk(self):pass
def fly(self):pass
def cal_flying_speed(self):pass
def cal_flying_height(self):pass
class Parrot(FlyAnimal):
def fly(self):pass
def cal_flying_speed(self):pass
def cal_flying_height(self): pass
所有会飞的动物 具有一些会飞的动物的特性
所有会走的动物 具有一些会走的动物的特性
在python中根本就没有一个叫做interface的关键字,上面的代码只是看起来像接口,
其实并没有起到接口的作用,子类完全可以不用去实现接口 ,
如果非要去模仿接口的概念,可以借助第三方模块:
http://pypi.python.org/pypi/zope.interface
twisted的twisted\internet\interface.py里使用zope.interface
文档https://zopeinterface.readthedocs.io/en/latest/
设计模式:https://github.com/faif/python-patterns
接口类的作用:
在java中,能够满足接口隔离原则,且完成多继承的约束。
而在python中,满足接口隔离原则,由于python本身支持多继承,所以就不需要接口的概念了。
抽象类和接口类
在python中并没有什么不同,都是用来约束子类中的方法。
只要是抽象类和接口类中被abstractmethod装饰的方法,都需要被子类实现。
需要注意的是,当多个类之间有相同的功能也有不同的功能的时候,应该采用多个接口类来进行分别的约束。
抽象类是python中定义类的一种规范。
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),
而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。
在java中,抽象类和接口截然不同。
抽象类的本质还是一个类,是类就必须遵循单继承的规则,所以一个子类如果被抽象类约束,
那么它只能被一个父类控制,当多个类之间有相同的功能也有不同的功能的时候,java只能用接口来解决问题。
(使用interface关键字)
1.多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口。
2.方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现。
注:在公司类写代码的时候,如果遇到抽象类,记得按照抽象类中的规范一一实现对应的方法。
为何要用接口
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
然后让子类去实现接口中的函数。
这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。
再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样。
多态
多态指的是一类事物有多种形态
例如动物有多种形态:人类,狗,猫。
文件有多种形态:文本文件,可执行文件
import abc
class File(metaclass=abc.ABCMeta): #同一类事物:文件
@abc.abstractmethod
def click(self):
pass
class Text(File): #文件的形态之一:文本文件
def click(self):
print('open file')
class ExeFile(File): #文件的形态之二:可执行文件
def click(self):
print('execute file')
多态性
一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)
多态性是指在不考虑实例类型的情况下使用实例
在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),
不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。
所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,
虽然二者消息一样,但是执行的效果不同。
例:
peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()
题外话:
java c++ c# —— 强类型语言
相同数据类型之间做运算
def func(int a):pass
func('a')
shell语言 —— 弱类型语言
1+'1'
def func(a):pass
1 'a' [1,2,3] ()
介于 强类型 与 弱类型之间 —— python 动态强类型语言
相同数据类型之间做运算
def func(a):pass
例:
class Payment:
def pay(self):pass
class QQpay(Payment):
def pay(self,money):
print('使用qq支付了%s元'%money)
class Wechatpay(Payment):
def pay(self,money):
print('使用微信支付了%s元'%money)
def recharge(self):pass
def pay(Payment pay_obj,int money):
# java 多态 在一个类之下发展出来的多个类的对象都可以作为参数传入这里
pay_obj.pay(money)
# 无论是python的2.*还是3.* : 天生自带多态效果
# qq_obj = QQpay()
# print(type(qq_obj)) # 一个对象的数据类型就是它所在的类
鸭子类型
逗比时刻:
Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
python程序员通常根据这种行为来编写程序。
例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。
例1:利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法。
例2:序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系。
例:下例的QQpay和Wechatpay我们就可以说它们互为鸭子类型。
class QQpay():
def pay(self,money):
print('使用qq支付了%s元'%money)
class Wechatpay():
def pay(self,money):
print('使用微信支付了%s元'%money)
def pay(pay_obj,money):
pay_obj.pay(money)
多态和鸭子类型
多态 通过继承实现
java 在一个类之下发展出来的多个类的对象都可以作为参数传入一个函数或者方法;
在python中不需要刻意实现多态,因为python本身自带多态效果。
鸭子类型
不是通过具体的继承关系来约束某些类中必须有哪些方法名;
是通过一种约定俗成的概念来保证在多个类中相似的功能叫相同的名字。
end
2018-4-16
相关文章:

系统crash无法启动 tpm error / could not read size 0x8000000e
系统crash无法启动 tpm error / couldn’t read size 0x8000000e 原文连接: https://unix.stackexchange.com/questions/305719/a-tpm-error-7-occurred-attempting-to-read-a-pcr-value-in-centos 内容: 问题: I’m getting this error while booting…

ASP.NET文件的下载
/// <summary>/// 下载文件/// </summary>/// <param name"filePath">文件的路径</param>/// <param name"fileName">文件名(有时候文件名存在数据库中用于替换路径中的文件名)</param>public void FileDownLoad(stri…

TestLink1.9.3测试用例:Excel转换XML工具一
最近在整理测试用例,所以想找一个合适的工具来完成对测试需求、测试用例的管理。对比了一翻,发现开源工具中扩展比较好的还属TestLink,而且还可以与JIRA进行对接,这样就引起了我更大的兴趣。加上之前本来就接触过此工具࿰…

MYSQL 使用自定义表变量
mysql 用户自定义表变量,ENGINEMyISAM DEFAULT CHARSETgb2312; 制定编码方式,防止乱码 DROP TABLE IF EXISTS p_temp; create temporary TABLE p_temp ( RowIndex int ,PRIMARY KEY (RowIndex))ENGINEMyISAM DEFAULT CHARSETgb2312; 转载于:https:/…

early EOF fatal: index-pack failed
early EOF fatal: index-pack failed 原文链接: https://stackoverflow.com/questions/21277806/fatal-early-eof-fatal-index-pack-failed 内容: First, turn off compression: git config --global core.compression 0 Next, let’s do a partial clone to truncate the a…

linux下运行python unitest_Python unittest打印日志可以在Linux上运行,但在Windows上不行...
我正在尝试编写一个unittest,它将stdout和stderr重定向到一个写在Windows网络驱动器上的文件。出于某些原因,相同的脚本(只有diff.是目录路径)可以在Linux上工作,但在Windows上不行。在Windows上运行时,不会将任何内容写入日志文件…

emacs 探索之五:latex配置
最近需要使用Latex写论文,之前一直在用emacs,而且渐渐理解emacs的思想之后发现大多数事情都能够在emacs中完成,那么自然会想到emacs是否能够与latex相结合。Google一下发现好多方式,当前前提是需要安装latex软件,然后e…

自动填充脚本使用及注意事项
网站开发需要,找了几个js脚本,最后选择了jQuery Autocomplete Mod(http://www.pengoworks.com/workshop/jquery/autocomplete.htm) 稍作修改,改动处见中文注释 1 jQuery.autocomplete function(input, options) {2 …

FFmpeg 与媒体文件关系
1. 容器/文件(Container/File):即特定格式的多媒体文件,比如MP4,flv,mov等。 2. 媒体流(Stream):表示在时间轴上的一段连续的数据,比如一段声音数据、一段视频…

一些可能没用过的调试窗口
首先说明:如果没有进入调试模式的话,默认的调试窗口如下: 开始前的准备: 新建控制台程序DebugWindowDemo: 修改Program.cs 的代码为: using System; using System.Threading; using System.Threading.Tasks…

linux 系统崩溃完全没有操作空间的系统修复
linux 系统崩溃完全没有操作空间的系统修复 1、通过U盘系统启动 2、修复文件系统 https://editor.csdn.net/md/?articleId106213788 此时硬盘会被挂在到U盘系统下作为一个目录, 例如/dev/sda2 修复它: fsck -y /dev/sda2很多时候都有效 3、修复grub

搜索进程内存地址_Linux编程 6 (查看进程 ps 及输出风格)
一.查看进程命令ps1.1 默认ps 命令在默认情况下,ps命令只会显示运行在当前控制台下,属于当前用户的进程,在上图中,我们只运行了bash shell以及ps命令本身。 上图中显示了程序的进程ID(1538,1583),它们运行在…

关于最大子段和线性算法的证明
重复题目: 输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 此题最初载于 http://blog.csdn.net/v_JULY_v/article/details/6444021 我在文…

SQL Server使用侦听器IP访问时遇到The target principal name is incorrect. Cannot generate SSPI context...
SQL Server使用侦听器IP访问时遇到"The target principal name is incorrect. Cannot generate SSPI context" 原文:SQL Server使用侦听器IP访问时遇到"The target principal name is incorrect. Cannot generate SSPI context"在测试SQL Server 2016 Alwa…

linux+Qt 下利用D-Bus进行进程间高效通信的三种方式
linuxQt 下利用D-Bus进行进程间高效通信的三种方式 原文链接: https://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html D-Bus概述 什么是D-Bus? D-Bus是一种进程间通信的机制,它被设计成为一种低开销、低延迟的IPC,并被多种桌面环…

xbmc-12.0稳定版代码初探 (2) —— XBMC_HOME
XBMC工程在debug时要设置XBMC_HOME的环境 用于指定ffmpeg的Dll文件位置,语言等等 xbmc/filesystem/SpecialProtocol.cpp 定义了一些如: CSpecialProtocol::SetXBMCPath();的函数 xbmc\Application.cpp InitDirectoriesWin32(); -> CUtil::GetHomePat…

python是最好的语言 永远二十岁_Python是世界上最好的语言吗?
编程语言的选择是IT圈子永远的争议。在任意一个程序员聚集的场合,喊一句类似于“PHP是世界上最好的语言”这样的话,肯定会惹来不少人和你争论得面红耳赤。那么,python是世界上最好的语言吗?这个我不敢说,但是至少他应该…

(转)Android笔记--handler机制
一、重要参考资料 【参考资料】目前来看,下面的几个网址中的内容质量比较不错,基本不需要再读别的网址了。1、android消息机制一http://xtfncel.javaeye.com/blog/6635172、Android消息机制二http://xtfncel.javaeye.com/blog/6635183、Android线程间通信…

自制操作系统Antz(9)——实现内核 (下) 实现图形化界面
Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html Linux内核源码分析地址:https://www.cnblogs.com/LexMoon/category/1267413.html Github项目地址:https://github.com/CasterWx/AntzOS 在前几天的任务中ÿ…

python迷宫万花筒代码_利用广度优先遍历搜索迷宫的python源代码
广度优先遍历简称为DFS,是数据结构中比较常用的一个算法,主要原理是采用队列先进先出的规则,一层一层的访问图的节点。而迷宫问题接近与遍历,但是不同于遍历,主要考虑是采用栈的形式标记路径,并对当前节点和…

联想拯救者Y9000-ubuntu-nvidia-驱动安装
概述 由于联想拯救者Y9000的硬件都比较新,所以在安装ubuntu 的时候会有很多驱动的问题,本文主要讲解安装nvidia驱动的问题,如网卡、触摸板无效的其他问题请在我的其他文章中查找 友情提示 安装完系统之后先插网线装ssh服务, 确…

修改远程桌面端口
修改远程桌面端口需要两个步骤: 1、打开注册表 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp],修改右边PortNamber的值,其默认值是3389,修改成所希望的端口即可,例如3…

开发管理 CheckLists(4) -风险管理
本文章主要介绍在项目启动前怎么样分步骤的去识别风险,才去什么方式去识别风险. 有需要做风险识别的朋友可以按照下面的步骤简单的走上一遍,或者可以提高项目的成功率 注意:本文章只是你做风险识别的chekcLists ,上面提到的一些分析方法都只是简单的介绍…

python的深拷贝与浅拷贝
对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量. 并不是复制⼀份内容. 两个变量的内容其实为一个地址,如果要在复制的同时分配新的地址则需要用到深拷贝和浅拷贝的命令 lst1 ["何炅", "杜海涛","周渝⺠", ["麻花藤", …

safari post 请求接收不到_我是谁?我在哪?我要到哪去?——HTTP请求头
各位小白帽们好又到了新一期的知识点咯在正片开始之前再次提醒一下各位因为联盟管理的需要本周五(12月4日)5点半将会对各位在平台的答题分数进行统计筛选部分排名靠前的童鞋作为核心的正式会员考核压力来了大家是不是有点紧张呢只要积极学习知识积极参与答题向本AI卖萌要flag相…

SharePoint 2013 配置开发环境,需安装VS2012插件
SharePoint 2013已经安装好了,接下来就是配置开发环境,安装VS2012,但是,装好了以后,发现没有SharePoint 2013开发的支持,如下图: 然后,去网上查找资料,VS2012对SharePoin…

联想拯救者Y9000-ubuntu-U盘启动失败解决方法
注意事项 1、U盘要是USB3.0的U盘,否则基本会失败 安装到最后的时候报一个 cd/dvd 设备 low speed的故障 2、bios 设置 硬盘模式 选择 AHCImode 模式, 否则刷机不成功 3、 U盘镜像的烧录方式, 实测windows 下的rufus工具有效

RedHat Enterprise 5.1下OpenLDAP的配置及PAMNSS的配置
服务器端 192.1.0.160 客户机端 192.1.0.221 一、在服务器端配置LDAP服务: 1.下载 openldap-2.4.11.tar.gz和db-4.7.25.tar.gz 2.安装BerkeleyDB #rpm -qa|grep db # tar xvf db-4.7.25.tar.gz # cd db_4.7.25# cd build_unix/# ../dist/configure -prefix/usr/loca…

pwn with glibc heap(堆利用手册)
前言 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅。 文中未做说明 均是指 glibc 2.23 相关引用已在文中进行了标注,如有遗漏,请提醒。 简单源码分析 本节只是简单跟读了一下 malloc 和 free 的源码&am…

COCO KeyPoints关键点数据集准备
COCO KeyPoints关键点数据集准备 概述 网上搜了一圈,coco关键点数据集准备的内容比较少,这里写一篇完成的标注流程到数据集准备的文章,以备后忘 标注工具 coco官方标注工具: coco–annotator https://github.com/jsbroks/coco-annotator …