python鸭子类型
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就能够被称为鸭子”
python的鸭子类型的设计让python的诸多对象的分类和应用更加灵活,需要注意类型和对象的区别(python的类也是对象),类型概念包含的范围更广,比如可迭代类型就包括list,tuple等类,这里list和tuple是类的概念,可迭代类型是类型的概念,可以看到可迭代类型包含了list和tuple这两个类,所以说类型的概念大于类的概念,当然一个类可以是属于多个类型的,比如list既属于可迭代类型,又属于序列类型。
python内置了一些类型,比如上面说的可迭代类型,还有数值类型(int,float,bool等),序列类型(list,str,tuple等),上下文管理类型(可以使用with语句的类型)等等。
那么这和鸭子类型有啥联系呢,再回到第一句话,一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就能够被称为鸭子。这里不要去把鸭子理解为我们日常生活中见到的那种真正的鸭子,而是应该把它理解为一个类型(类型,而不是类),我们平时说的鸭子当然本身就属于鸭子类型了,但是如果现在还有一类鸟(类,而不是类型)也看起来像鸭子,游泳像鸭子,叫起来叫鸭子,虽然不是真正的鸭子,我们也把它归类到鸭子这个类型里面,这样做有什么好处呢?比如你们部门去野炊,你领导让你去抓一只鸭子来,并且说只要是鸭子类型的都可以,这时候你就不必限定只抓真的鸭子,只要是看起来像鸭子,游泳起来像鸭子,叫起来像鸭子的都可以,这就很灵活了。再放到代码中来理解一下
我们定义:实现了gaga方法的对象都属于鸭子类型,实现了wangwang方法的对象都属于狗子类型,并且规定只要属于鸭子类型的对象就可以输出“i am duck”,只要是属于狗子类型的对象就可以输出“i am dog”
class Animal01(object):
def gaga(self):
pass def wangwang(self):
pass def __str__(self):
return "animal01" class Animal02(object):
def gaga(self):
pass def __str__(self):
return "animal02" class Animal03(object):
def wangwang(self):
pass def __str__(self):
return "animal03" animal_list = [Animal01(), Animal02(), Animal03()] # 实例化三个对象 for animal in animal_list:
try:
animal.gaga() # 如果实现了gaga方法,那么就认为它是鸭子类型
print(animal, "is duck")
except Exception: # 如果没有实现gaga方法,说明不是鸭子类型
pass for animal in animal_list:
try:
animal.wangwang() # 如果实现了wangwang方法,那么就认为它是狗子类型
print(animal, "is dog")
except Exception:
pass 输出结果:
animal01 is duck
animal02 is duck
animal01 is dog
animal03 is dog
可以看到animal01实现了gaga也实现了wangwang方法,即,animal01既看起来像鸭子,也看起来像狗子,所以它既是鸭子类型也是狗子类型,所以输出结果中都有它,其余两种要么看起来只像鸭子,要么只像狗子。
那具体在python中有什么体现呢?
比如python的列表有个方法叫extend,先看下这个函数的定义:
作用是在一个列表后面拼接另一个可迭代类型的对象,比如:
list_a = [1, 2, 3]
list_b = [4, 5]
set_c = (6, 7) list_a.extend(list_b)
list_a.extend(set_c)
print(list_a) 输出结果:
[1, 2, 3, 4, 5, 6, 7]
可以看到list_b是一个列表,set_c是一个集合,他们都是可迭代类型,都可以通过list_a的extend方法拼接到list_a后面,这样就体现了python的灵活性了,因为按我们一般的思路,一个列表后面只能是拼接一个列表才对,可是这里却不这么限定,只要是个可迭代类型就都可以拼接,极大丰富了应用的范围。这就体现了鸭子类型的优势了,list和set都是可迭代类型(即都看起来像鸭子),只要是可迭代我就给你可拼接到一个列表的功能(只要是鸭子类型就可以做某件事)
最新文章
- 干货分享:SQLSERVER使用裸设备
- kafka性能参数和压力测试揭秘
- Python高级特性学习笔记
- Django project structure: how does static folder, STATIC_URL, STATIC_ROOT work
- Flume 实战(2)--Flume-ng-sdk源码分析
- Chr()和chrb()的含义(转)
- cocos2d-x 不能在android真机debug的问题
- 一个CSS小测试
- Sizzle一步步实现所有功能(基本筛选)
- 每天进步一点点——再次了解Linux进程ID
- Python学习入门基础教程(learning Python)--2.3.3Python函数型参详解
- v3学院带你一次性认清UART、RS-232、RS-422、RS-485的区别
- wifipineapple的evilportal
- JSF-使用JSF标记
- Identity Server 4 - Hybrid Flow - Claims
- python Ajax
- C#操作Access数据库中遇到的问题(待续)
- [转]使用js把Unix时间戳转化成普通日期
- hive -f 传递参数
- 云存储的未来:Scale Up还是Scale Out?
热门文章
- TensorFlow 报错 ValueError: Can't load save_path when it is None.
- mysql优化查找执行慢的sql
- 如何优雅地执行dubbo";单测";
- mybatis三个执行器的差别
- Web打印的解决方案之证件套打
- input file上传文件弹出框的默认格式设置
- fluid.io.load_inference_model 载入多个模型的时候会报错 -- [paddlepaddle]
- H3C交换机恢复出厂设置
- mysql判断表字段或索引是否存在,然后修改
- python安装 werkzeug