用python画小鸭_python中的鸭子类型(协议)和接口

news/2024/10/30 15:30:02/

定义

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)

参考资料:


http://www.ppmy.cn/news/271295.html

相关文章

mysql小鸭子_可读代码编写炸鸡十一 - 小黄鸭从你的心里游到脑子里

可读代码编写炸鸡十一 - 小黄鸭从你的心里游到脑子里 多选参数推荐搜索 数据结构与算法 可读代码编写 Java Redis MySQL 大家好,我是多选参数的大炮。 可读代码编写的炸鸡很快要写到头了,从一开始的尝试到现在的倒计时,还是有一些成就感的。当…

小鸭

那是在我五岁的时候,那年我妈妈去了外地打工,就剩下爸爸在家靠骑黄包车来养活我。有一天,爸爸带着一只黄毛小鸭回来。他告诉我说是从一辆装运鸭子的大货车上掉下来的,他恰好经过,于是就把它带了回来。 爸爸还嘱咐我说&…

数据结构和算法 | 第一部分第二课:小鸭子们去旅行

作者 谢恩铭,公众号「程序员联盟」。 转载请注明出处。 原文:https://www.jianshu.com/p/31d14bd080d4 内容简介 引出算法复杂度的故事两种算法两种算法的对比第一部分第三课预告 1. 引出算法复杂度的故事 上一课 数据结构和算法 | 第一部分第一课&…

计算机学win7画图,Windows7电脑基础使用画图程序画一个小鸭

1、启动程序 1)单击“开始-所有程序-附件-画图”,这样就打开了画图窗口 2)在窗口中,上边是工具栏,里面包含有菜单按钮和许多画图工具,像铅笔、线条、颜色等; 3)中间是工作区,里面有一个空白的画布,可以在里…

java基础_设计模式_设计基础(小鸭子游戏)

小鸭子游戏,是好多爱好者接触设计模式、认知设计模式概念的一个入门。 每个初学者的理解不同,我加上自己的理解大体是这样的:前提是处理大规模时,假设池塘中有10000头小鸭子,有红头鸭,野鸭子,木…

Android移动应用开发——实验七——小鸭子报数(广播)

 掌握布局与控件的使用方法  掌握有序广播机制,根据广播接收者的优先级顺序接收广播  掌握广播拦截机制 通过合理布局来搭建界面,界面效果如下图所示。采用有序广播方式,将下方小鸭子优先级分别设置1000、800、600。 1、当点…

用MATLAB求解小鸭过河曲线

题目描述 有只鸭子想游到河对岸的某个位置O,如果它的方向始终朝着目标O。求这只鸭子的游动曲线。问题分析 由于水流速度会对运动产生影响,此时小鸭朝向对岸的方向是一个随时变化的,合速度的方向和大小也是变化的,小鸭的运动轨迹将…

6综合项目 旅游网 【6.我的收藏和收藏排行榜】

我的收藏 分析 先登录→拿到当前登录的用户信息,从数据库中获取uid和对应uid的rid集合→将rid集合信息展示到我的收藏 前台代码 判断用户是否登录,传递uid,通过uid查找其对应的rid集合 当查询的属性涉及到多张表,则必须使用多表连…