用python画小鸭_python中的鸭子类型(协议)和接口
定义
1. 接口(interface)
学过静态语言的同学一定对接口的概念并不陌生,它类似于我们家里用的插座标准,要用电器时,我们得先查看对应的插头是否和插座孔匹配。也正因为此,接口给我们提供了很大的方便,比如,我们对应看到三孔的插头,一般使用在冰箱,空调等大功率电器上。可以这么说,它给我们限定了一个边界,让我们看到接口,就知道它有哪些作用
2. 鸭子类型(Duck Typing) / 协议(Protocols)/ 非正式接口(Informal Interfaces)
这几个概念在python中是一个意思,以下我仅用协议作为指代
python中有一个可爱的概念是鸭子类型,还有一句与之对应的至理名言
If it talks and walks like a duck, then it is a duck
如果我们在运行时,用到一个对象,能够像鸭子一样,呱呱叫,做冲鸭的动作
那么,我们就将它当做鸭子对象处理。这就是鸭子对象(即协议或非正式接口),协议就是我们约定俗成的,大家都默认遵守的规矩。正因为python具有这个特性,它因此变得相当灵活。比如,你在使用一个对象时,不用再去校验对象的类型,才去使用,而是可以直接去实验是否有这个功能,如果有就可以继续下一步,而如果没有,就直接报错。这样做可以大大节省我们的开发时间,而python内部有很多定义好的协议供我们使用,带双下划线的魔法方法(如__init__、__iter__、__str__等)都是。
示例
1. 接口(interface)
[code lang=”py”]
import abc
class Programmer(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def code(self):
return "code"
[/code]
abc这个包提供各种抽象基类的方法,我们可以通过继承、复用它的方法实现一个自定义抽象接口类,比如这里,我们通过将元类设置成abc.ABCMeta,通过实现它的abstractmethod方法定义一个抽象接口。当然还有别的实现方式,可以参考我文末给出的参考链接查看
2.协议(Protocols)[
[code lang=”py”]
class Programmer:
def __len__(self):
return 20
p = Programmer()
print(len(p))
[/code]
原本我们的类是没有长度这个属性的,这里我们给这个类添加了协议方法__len__,使得它能够被len调用。在代码中,我们可以充分利用它的特性,增强我们类的基本功能使得类功能更加强大,代码更加精简
特点
1. 接口(interface)
实现接口前,我们会定义一个抽象基类(示例1),但这个基类不可以被直接实例化
抽象基类的一般使用方式是,让别的类继承并实现特定的抽象方法(示例1中被@abc.abstractmethod包裹的方法)
我们一般可以通过判断某个对象是否为某个类的方式,判断某个对象是否默认具有某种特征,如判断isinstance(obj, list),这里判断obj是否为list类,以判断时候可以迭代
2.协议(Protocols)[mks_separator style=”solid” height=”2″]可以通过实现内部的模仿方法拓展类,使得类变得更加强大
动态语言的灵活性通过协议的机制体现出来,使用时不需要判断类型,如果通过就默认具备某种特征,否则就没有该特征,简洁优雅
使用示范
1.猴子补丁
[code lang=”py”]
class Programmer:
def __init__(self, iterable):
self._data = list(iterable)
def __len__(self):
return len(self._data)
def __getitem__(self, index):
return self._data[index]
[/code]
定义一个Programmer类对象,我们此时在程序运行的过程中,对它进行动态改造,看下如何实现
[code lang=”py”]
from programmer import Programmer
p = Programmer(range(20))
def set_item(temp, i, item):
… temp._data[i] = item
…
Programmer.__setitem__ = set_item
p[1] = 2233
for i in p:
… print (i)
…
输出:
>>>0
>>>2233
>>>2
>>>3
>>>4
>>>.
>>>.
>>>.
>>>19
[/code]
我们在程序运行的时候,对Programmer这个对象增加了__setitem__功能,实现动态添加我们需要的功能,十分方便
2.注册方法
除了通过继承抽象基类的方式实现接口,我们还可以通过注册方法实现接口,也有一种说法叫做虚拟子类,它能够在即使不继承基类的情况下,依然被视作基类的子类。很绕是不是,我们看个例子就明白了
[code lang=”py”]
import abc
class Programmer(abc.ABC):
@abc.abstractmethod
def code(self):
pass
@Programmer.register
class Tom:
pass
t = Tom()
print(issubclass(Tom, Programmer))
print(isinstance(t, Programmer))
输出结果:
>>>True
>>>True
[/code]
我们可以很清楚的看见,通过注册的方式实现子类,我们即使不实现基类的方法也没有关系,而且最后的输出结果我们可以看出,它们也是被视作基类的子类,但一般我们不推荐这种做法,很显然,这样的代码放到日常开发中,估计要被拉出去墙角嘲讽一个月
一点建议
1. 除非必要,不要自己实现抽象基类,这就失去了动态语言的灵活性
2. 在实现抽象基类前,要先去标准库中寻找基类,绝大部分抽象基类,官方已经贴心的为我们准备好了(https://docs.python.org/3/library/collections.abc.html#module-collections.abc)
参考资料:
用python画小鸭_python中的鸭子类型(协议)和接口相关推荐
- 用python画小鸭,Python 处理输入法字库(五笔极点字库转小鸭字库)
Python 处理输入法字库(五笔极点字库转小鸭字库) Python 处理输入法字库(五笔极点字库转小鸭字库) 一直都是用的小鸭五笔,091新字库是极点格式的,刚开始懒得动,直接用极点五笔了,用了一段 ...
- python画xy轴_python中的坐标轴该如何画?好画吗?
曾经的数学爱搭不理,结果在工作中发现需要用python去解决相关的问题.数学不好的小伙伴已经开始发愁了.不要着急,小编跟你们一起想办法.为了方便python小白的理解,我们还是从最基础的入手.基础知识 ...
- python画三维坐标_Python中三维坐标空间绘制的实现
在三维空间绘制点,线,面 1.绘制点 用scatter()散点绘制三维坐标点 from matplotlib import pyplot as plt from mpl_toolkits.mplot3 ...
- python画一个点_python中画散点图
示例代码: import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D dat ...
- python画小动物_Python学习之print打印十二生肖
我们知道,Python打印Hello world是非常简单的,只要输入 print("Hello world") 就行了. Python字符串使用Unicode编码来表示文本.对 ...
- python画指数函数图像_python中指数函数的回归线拟合
我正在学习如何解释用Python创建的指数函数的线性回归模型.我创建了一个模型,首先通过取自然对数将指数Y数据转换成直线.然后我创建一个线性模型,并记录坡度和截距.最后,我尝试使用斜率和截距来计算样本 ...
- python算法和数据结构_Python中的数据结构和算法
python算法和数据结构 To 至 Leonardo da Vinci 达芬奇(Leonardo da Vinci) 介绍 (Introduction) The purpose of this ar ...
- 用python画小黄人-怎么用python画小黄人
怎么用python画小黄人? 前言: 还记得小黄人哪只蠢萌蠢萌的单眼小黄人?就是喜欢做什么事都喜欢逞能的那只,下面用Python来实现一下,正在逃跑的小黄人. 一.导入Turtle库 import t ...
- 如何用python画小黄人_怎么用python画小黄人
怎么用python画小黄人?TB1免费资源网 前言:TB1免费资源网 还记得小黄人哪只蠢萌蠢萌的单眼小黄人?就是喜欢做什么事都喜欢逞能的那只,下面用Python来实现一下,正在逃跑的小黄人.TB1免费 ...
最新文章
- 操作系统学习:Linux0.12初始化详细流程-首个子进程
- 设计模式之模板模式学习笔记
- js 如何获取class的元素 以及创建方法getElementsByClassName
- java 类.class_面试官:Java反射是什么?我回答不上来!
- 编译我的hello.ko
- java实现逾期提醒_信用卡逾期后的5个阶段 你都知道吗?
- 2014年图灵奖_2014年人民选择奖:投下您的一票
- echarts中graphic_Echarts实现折线图
- 大数据之-Hadoop3.x_MapReduce_MapJoin案例完成---大数据之hadoop3.x工作笔记0134
- 华为4g显示无服务器,华为nova5 插卡无4G
- Android中动态调整ImageView的宽高比
- wps 安装字体手册
- Java获取四分位数
- golang中net/http包用法
- 第三方支付平台——业务介绍(龙果)
- ffmpeg添加补白mp3
- 陕西师范大学,我终于来了!
- WGS84(GPS坐标) BD09坐标(百度坐标)GCJ02(国测局坐标) 的相互转换
- Unity热更新ToLua框架学习
- (架构)后端技术体系框架