首页 > 编程语言 >Python的鸭子类型

Python的鸭子类型

时间:2023-12-18 15:03:29浏览次数:22  
标签:calculate Python 对象 鸭子 duck 类型 def

编程语言具有类型概念,例如Python中有数字类型、字符串类型、布尔类型,或者更加复杂的结构,例如元组 tuple 、列表 list 、集合 set 和字典类型 dict 等等。

根据如何将类型解析并赋值给各种构造(例如变量,表达式,函数,函数参数等),编程语言可以归类为“鸭子类型”,“结构化类型”或“标称类型”。

本质上,分类决定了对象如何被解析并推断为具体的类型。

鸭子测试

鸭子类型( duck typing )语言使用鸭子测试来评估对象是否可以被解析为特定的类型。Python就是其中一种。

这个概念的名字来源于由詹姆斯·惠特科姆·莱利提出的鸭子测试。“鸭子测试”可以这样表述:

“如果看起来像鸭子,叫起来像鸭子,那么它一定是鸭子。”

If it looks like a duck and quacks like a duck, it must be a duck.

--- James Whitcomb Riley

Python的鸭子类型_鸭子类型

鸭子类型

鸭子类型在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。

在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。

在常规类型中,我们能否在一个特定场景中使用某个对象取决于这个对象的类型,而在鸭子类型中,则取决于这个对象是否具有某种属性或者方法——即只要具备特定的属性或方法,能通过鸭子测试,就可以使用。

Python术语

Python术语表中的鸭子类型 duck-typing :

A programming style which does not look at an object’s type to determine if it has the right interface; instead, the method or attribute is simply called or used (“If it looks like a duck and quacks like a duck, it must be a duck.”) By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). (Note, however, that duck-typing can be complemented with abstract base classes.) Instead, it typically employs hasattr() tests or EAFP programming.

译文:

鸭子类型是一种编程风格,决定一个对象是否有正确的接口,关注点在于它的方法或属性,而不是它的类型(“如果它看起来像鸭子,像鸭子一样嘎嘎叫,那么它一定是鸭子。”)。通过强调接口而不是特定类型,设计良好的代码通过多态提高了灵活性。鸭子类型无需使用 type() 或 isinstance() 进行检查(注意,鸭子类型可以用抽象基类来补充),相反,它通常使用 hasattr() 来检查,或是 EAFP 编程。

代码示例

举个例子:

# 定义一个计算函数,接收3个入参
def calculate(a, b, c):
    return (a + b) * c


# 分别计算3种情况的结果
result1 = calculate(1, 2, 3)
result2 = calculate([1, 2, 3], [4, 5, 6], 2)
result3 = calculate("打工人", "打工魂", 3)

# 打印3种结果
print(result1, result2, result3, sep='\n')

代码解释:在上面的例子中,我们每次调用 calculate() 都使用的是不同的对象(数字、列表和字符串),并且它们在继承关系中没有联系。只要输入对象支持 + 和 * 方法,操作就能成功。

执行后输出:

9
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
打工人打工魂打工人打工魂打工人打工魂

这样,鸭子类型在不使用继承的情况下使用了多态。

再举个栗子:

# 鸭子类
class Duck:

    def quack(self):
        print("这鸭子正在嘎嘎叫")

    def feathers(self):
        print("这鸭子拥有白色和灰色的羽毛")

# 人类
class Person:

    def quack(self):
        print("这人正在模仿鸭子")

    def feathers(self):
        print("这人在地上拿起1根羽毛然后给其他人看")


# 函数/接口
def in_the_forest(duck):
    duck.quack()
    duck.feathers()


if __name__ == '__main__':

    donald = Duck()  # 创建一个Duck类的实例
    john = Person()  # 创建一个Person类的实例

    in_the_forest(donald)  # 调用函数,传入Duck的实例
    in_the_forest(john)    # 调用函数,传入Person的实例

代码运行后输出:

这鸭子正在嘎嘎叫
这鸭子拥有白色和灰色的羽毛
这人正在模仿鸭子
这人在地上拿起1根羽毛然后给其他人看

总结

鸭子类型是一个与动态类型( dynamic typing )相关的概念,其中关注的是它定义的方法,而不太关注对象的类型或所属类。当您使用鸭子类型时,你无需做检查类型。相反,您要检查给定方法或属性是否存在。

鸭子类型语言为程序员提供了最大的灵活性,程序员只需写最少量的代码。但是这些语言可能并不安全,可能会产生运行时错误,使用时需要格外注意。

标签:calculate,Python,对象,鸭子,duck,类型,def
From: https://blog.51cto.com/u_15590807/8873849

相关文章

  • 一篇文章带你了解Python之Selenium自动化爬虫
    Python之Selenium自动化爬虫0.介绍Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Selenium可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器(2018年开发者说暂停开发,chromedriver也可以实现同样的功能)),可以接收指令,让浏览器自动加......
  • Python多线程应用于自动化测试操作示例
    本文实例讲述了Python多线程应用于自动化测试操作。分享给大家供大家参考,具体如下:多线程执行测试用例实例:importthreadingfromtimeimportsleep,ctimefromseleniumimportwebdriver#测试用例1deftest_baidu(browser,search):print("开始,现在时间是%s"%ctime())print("......
  • 在Python中进行自动化单元测试的教程
    一、软件测试大型软件系统的开发是一个很复杂的过程,其中因为人的因素而所产生的错误非常多,因此软件在开发过程必须要有相应的质量保证活动,而软件测试则是保证质量的关键措施。正像软件熵(softwareentropy)所描述的那样:一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地......
  • 在Python中,你可以使用面向对象的方法来创建一个甘特图的模板。以下是一个使用`matplot
    在Python中,你可以使用`matplotlib`或者`plotly`库来制作甘特图¹²⁴⁵。以下是一些示例:**使用matplotlib制作甘特图**¹:```pythonimportmatplotlib.pyplotasplt#设置字体和负号显示plt.rcParams['font.sans-serif']=['SimHei']plt.rcParams['axes.unicode_minus']=F......
  • Redis上层数据类型设计
    StringString即字符串对象,是Redis使用最多的数据类型,其使用key-value结构,key为唯一标识,value为存储内容。value不仅可以是字符串,也可以是数字,包括整数或者浮点数。value最多可以容纳的大小为512MB。>SETnameErickRenOK>SETage19OK>GETname"ErickRen">GETage......
  • python openstacksdk
     参考:openstackregionlist获取yaml配置的域信息ragion_name,也可以通过配置less/etc/neutron/neutron.conf获取region_name  openstacksdk旨在与任何OpenStack云对话。为此,需要一个配置文件。openstacksdk支持 clouds.yaml 文件,但也可以使用环境变量。......
  • 关于python http.server 开启多线程并发的问题
    问题描述thon中的http.server模块是单线程的,这意味着它一次只能处理一个请求,而其他请求必须等待。为了解决这个问题,您可以考虑使用多线程或异步处理来处理并发请求。您可以使用Python的ThreadingMixIn来创建一个支持多线程的HTTP服务器,或者考虑使用异步框架如asyncio来处理请求......
  • python动态规划求解最长回文子串
    回文是什么,回文是正着读和反着读都是一样的字符叫着回文。 如‘aba’,‘aa’,‘b’,这些都是回文classSolution:deflongestPalindrome(self,s:str)->str:n=len(s)dp=[[False]*nfor_inrange(n)]ans=""forlinrange(n):......
  • python递归求解青蛙跳台阶问题
    一只青蛙一次可以跳上1级台阶,也可以跳上2级。请问该青蛙跳上一个n级的台阶总共有多少种跳法。输入台阶数,输出一共有多少种跳法。defjump1(n):ifn==1:return1elifn==2:return2else:returnjump1(n-1)+jump1(n-2)x=eval(input())pr......
  • python回溯求解电话号码组合
    给定一个仅包含数字2-9的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意1不对应任何字母。输入:digits="23"输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]示例2:......