深入了解Python enumerate和zip


Posted in Python onJuly 16, 2020

enumerate

首先介绍的是enumerate函数。

在我们日常编程的过程当中,经常会遇到一个问题。

在C语言以及一些古老的语言当中是没有迭代器这个概念的,所以我们要遍历数组或者是容器的时候,往往只能通过下标。有了迭代器之后,我们遍历的过程方便了很多,我们可以直接用一个变量去迭代一个容器当中的值。最简单的例子就是数组的遍历,比如我们要遍历items这个数组。我们可以直接:

for item in items:

通过迭代器的方式我们可以很轻松地遍历数组,而不再需要下标,也不需要计算数组的长度了。但是如果我们在循环体当中需要知道元素的下标该怎么办?

难道我们真的只能在下标和迭代器当中选择一个吗,比如在循环体的外面添加一个变量来记录下标?

idx = 0
for item in items:
  operation()
  idx += 1

这样可以解决问题,但是很麻烦,一点也不简洁,用专业的话来说一点也不pythonic(符合Python标准的代码)。为了追求pythonic,于是有了enumerate函数,来解决了我们又想直接迭代又需要知道元素下标的情形。

它的用法也很简单,我们把需要迭代的对象或者迭代器传入enumerate函数当中,它会为我们创建一个新的迭代器,同时返回下标以及迭代的内容。我们来看一个例子:

for i, item in enumerate(items):

除此之外,enumerate还支持传入参数。比如在某些场景当中,我们希望下标从1开始,而不再是0开始,我们可以额外多传入一个参数实现这点:

for i, item in enumerate(items, 1):

循环是我们编程的时候必不可少的操作,也正因此,enumerate函数使用非常广泛。但是有一点需要注意,如果我们迭代的是一个多元组数组,我们需要注意要将index和value区分开。举个例子:

data = [(1, 3), (2, 1), (3, 3)]

在不用enumerate的时候,我们有两种迭代方式,这两种都可以运行。

for x, y in data:

for (x, y) in data:

但是如果我们使用enumerate的话,由于引入了一个index,我们必须要做区分,否则会报错,所以我们只有一种迭代方式:

for i, (x, y) in enumerate(data):

zip

接下来要介绍的另一个函数同样是方便我们迭代的,不过它针对的是另一个场景——多对象迭代。

它的应用场景非常简单,就是我们想要同时迭代多份数据,比如用户的名字和用户的职业数据是分开的,我们希望同时遍历一个用户的职业和名字。如果不使用zip,我们可能只能放弃迭代器回到传统的下标遍历的模式了。这样当然是可以的,不过有两个小问题,第一个小问题当然是代码的可读性变差了,不够pythonic,第二个问题是我们需要维护两个容器长度不一样的情况,会增加额外的代码。而使用zip,可以同时解决以上两个问题。

我们来看一个例子:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']
jobs = ['coach', 'student', 'student', 'student', 'professor']

for name, job in zip(names, jobs):
 print(name, job)

最后输出的结果是人名和职业的tuple:

xiaoming coach
xiaohua student
xiaohei student
xiaoli student

上面举的例子当中,names和jobs的长度其实是不一致的,在使用了zip的情况下,会自动替我们按照其中较短的那个进行截断。如果我们不希望截断,我们也可以使用itertools下的zip_longest来代替zip:

from itertools import zip_longest
for name, job in zip_longest(names, jobs):

这样的话长度不够的元素会以None来填充,zip_longest提供了一个参数fillvalue,可以填充成我们指定的值。

无论是zip还是zip_longest,都可以支持多迭代器的遍历。比如:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']
jobs = ['coach', 'student', 'student', 'student', 'professor']
hobbies = ['footbal', 'tennis', 'badminton', 'basketbal']

for name, job, hobby in zip(names, jobs, hobbies):
 print(name, job, hobby)

zip除了方便我们迭代遍历之外,另一个很大的用处是可以很方便地生成dict。比如刚才的例子当中,我们想生成一个名称和职业的dict,一般的办法当然是先定义一个dict,然后遍历所有的key和value,来生成dict。然而使用zip,我们可以将这个操作简化到一行代码:

jobDict = dict(zip(names, jobs))

需要注意的是,我们调用zip返回的结果其实是一个迭代器,我们在转化成dict的时候自动遍历了迭代器当中的内容。比如我们如果直接打印出zip调用结果的话,就会发现屏幕上输出的是一个迭代器的地址:

print(zip(names, jobs))
>>> <zip object at 0x10ec93b40>

我们想要获得它的内容,需要将它手动转成list:

print(list(zip(names, jobs)))
>>> [('xiaoming', 'coach'), ('xiaohua', 'student'), ('xiaohei', 'student'), ('xiaoli', 'student')]

无论是enumerate还是zip其实底层都是基于迭代器实现的,从原理上来说并没有什么太深奥的内容,而且我们不使用它们也不影响我们写代码。但是Python之所以是Python,之所以很多人称道它简洁的语言和逻辑,离不开我们广泛地使用这些简化代码逻辑的工具和方法。因此我们加以了解是非常有必要的,希望大家都能写出pythonic的代码,不仅写代码能力强,而且代码本身也漂亮。

以上就是深入了解Python enumerate和zip的详细内容,更多关于Python enumerate和zip的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
将Python中的数据存储到系统本地的简单方法
Apr 11 Python
python实现域名系统(DNS)正向查询的方法
Apr 19 Python
python的dataframe转换为多维矩阵的方法
Apr 11 Python
用PyInstaller把Python代码打包成单个独立的exe可执行文件
May 26 Python
Python 网络爬虫--关于简单的模拟登录实例讲解
Jun 01 Python
Python网络编程之使用TCP方式传输文件操作示例
Nov 01 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
Dec 12 Python
已安装tensorflow-gpu,但keras无法使用GPU加速的解决
Feb 07 Python
python 已知平行四边形三个点,求第四个点的案例
Apr 12 Python
快速解决jupyter notebook启动需要密码的问题
Apr 21 Python
python 双循环遍历list 变量判断代码
May 04 Python
解决Python中导入自己写的类,被划红线,但不影响执行的问题
Jul 13 Python
详细分析Python collections工具库
Jul 16 #Python
带你学习Python如何实现回归树模型
Jul 16 #Python
MATLAB数学建模之画图汇总
Jul 16 #Python
浅析Python迭代器的高级用法
Jul 16 #Python
python 使用递归的方式实现语义图片分割功能
Jul 16 #Python
Django serializer优化类视图的实现示例
Jul 16 #Python
python中plt.imshow与cv2.imshow显示颜色问题
Jul 16 #Python
You might like
PHP的类 功能齐全的发送邮件类
2006/10/09 PHP
Zend Framework动作助手FlashMessenger用法详解
2016/03/05 PHP
php使用include 和require引入文件的区别
2017/02/16 PHP
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
input 输入框内的输入事件详细分析
2010/03/17 Javascript
Visual Studio中的jQuery智能提示设置方法
2010/03/27 Javascript
js不能跳转到上一页面的问题解决方法
2013/03/01 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
详谈JavaScript 匿名函数及闭包
2014/11/14 Javascript
javascript实现label标签跳出循环操作
2016/03/06 Javascript
常用jQuery选择器汇总
2017/02/02 Javascript
jQuery插件FusionCharts实现的2D面积图效果示例【附demo源码下载】
2017/03/06 Javascript
AngularJS之页面跳转Route实例代码
2017/03/10 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
JS+html5制作简单音乐播放器
2020/09/13 Javascript
前端页面文件拖拽上传模块js代码示例
2017/05/19 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
js保留两位小数方法总结
2018/01/31 Javascript
在element-ui的el-tree组件中用render函数生成el-button的实例代码
2018/11/05 Javascript
从零开始在NPM上发布一个Vue组件的方法步骤
2018/12/20 Javascript
jQuery实现动态添加和删除input框实例代码
2019/03/26 jQuery
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
2019/05/18 Javascript
详解vue-property-decorator使用手册
2019/07/29 Javascript
简述Vue中容易被忽视的知识点
2019/12/09 Javascript
[52:41]OG vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/20 DOTA
python简单读取大文件的方法
2016/07/01 Python
Python学习笔记之if语句的使用示例
2017/10/23 Python
Python和Go语言的区别总结
2019/02/20 Python
基于HTML5 Canvas:字符串,路径,背景,图片的详解
2013/05/09 HTML / CSS
普通大学毕业生自荐信范文
2014/02/23 职场文书
销售经理岗位职责
2014/03/16 职场文书
公务员处分决定书
2015/06/25 职场文书
2015中学教师个人工作总结
2015/07/22 职场文书
2016中秋节问候语
2015/11/11 职场文书
忆童年!用Python实现愤怒的小鸟游戏
2021/06/07 Python
Mysql超详细讲解死锁问题的理解
2022/04/01 MySQL