本文始发于个人公众号:TechFlow,原创不易,求个关注

今天是Python专题的第7篇文章,我们继续介绍迭代相关。

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的更多相关文章

  1. Python专题之详解enumerate和zip

    enumerate 第一个是枚举函数. 在我们的日常编程过程中,我们经常遇到一个问题. 在C语言和一些古老的语言中没有迭代器的概念,所以当我们想要遍历数组或容器时,我们只能使用下标.使用迭代器,我们的 ...

  2. python线程详解

    #线程状态 #线程同步(锁)#多线程的优势在于可以同时运行多个任务,至少感觉起来是这样,但是当线程需要共享数据时,可能存在数据不同步的问题. #threading模块#常用方法:'''threadin ...

  3. Python闭包详解

    Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...

  4. [转] Python Traceback详解

    追莫名其妙的bugs利器-mark- 转自:https://www.jianshu.com/p/a8cb5375171a   Python Traceback详解   刚接触Python的时候,简单的 ...

  5. python 数据类型详解

    python数据类型详解 参考网址:http://www.cnblogs.com/linjiqin/p/3608541.html 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8 ...

  6. Python 递归函数 详解

    Python 递归函数 详解   在函数内调用当前函数本身的函数就是递归函数   下面是一个递归函数的实例: 第一次接触递归函数的人,都会被它调用本身而搞得晕头转向,而且看上面的函数调用,得到的结果会 ...

  7. python数据类型详解(全面)

    python数据类型详解 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8.字典9.日期 1.字符串1.1.如何在Python中使用字符串a.使用单引号(')用单引号括起来表示字 ...

  8. Python Collections详解

    Python Collections详解 collections模块在内置数据结构(list.tuple.dict.set)的基础上,提供了几个额外的数据结构:ChainMap.Counter.deq ...

  9. python生成器详解

    1. 生成器 利用迭代器(迭代器详解python迭代器详解),我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成.但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记 ...

随机推荐

  1. 使用java列举所有给定数组中和为定值的组合

    import java.util.Arrays; public class SolveProb { ]; ;// 记录当前 public SolveProb() { } public static v ...

  2. fetch API 和 ajax

    fetch('/some.json', { method: 'get', body: { id: 22 } }).then(function (resp) { resp.json().then(con ...

  3. 关于(Building tool)的认识以及当下流行的Building tool有哪些?

    1.Building tool是什么? (Building tool)构建工具是一种工具,它负责构建流程的所有内容,并自动化与构建项目相关的所有内容.它致力于以下任务: 生成源代码(如果在软件项目中使 ...

  4. 腾讯玩O2O手机维修 巨头入局引市场大变

     巨头入局引市场大变" title="腾讯玩O2O手机维修 巨头入局引市场大变">     对于"游击队"或初创企业来说,最怕的就是巨头的杀入. ...

  5. [PyTorch入门之60分钟入门闪击战]之训练分类器

    训练分类器 目前为止,你已经知道如何定义神经网络.计算损失和更新网络的权重.现在你可能在想,那数据呢? What about data? 通常,当你需要处理图像.文本.音频或者视频数据时,你可以使用标 ...

  6. MDEV入门

    ------------- MDEV入门------------- 对于我们这些人知道如何使用的mdev ,底漆可能似乎跛.为其他人的mdev是一个神秘的黑匣子,他们听到的是真棒,但不能似乎得到他们的 ...

  7. 关于C++类中的三兄弟(pretect、private、public)

    1.public修饰的成员变量 在程序的任何地方都可以被访问,就是公共变量的意思,不需要通过成员函数就可以由类的实例直接访问 2.private修饰的成员变量 只有类内可直接访问,私有的,类的实例要通 ...

  8. 一步到位datatabls中文化

    #一步到位datatabls中文化 加入以下代码 $(document).ready(function () { $('#declarationList').DataTable({ destroy:t ...

  9. JUC-八锁现象和不安全锁

    1,被 synchronized 修饰的方法,锁的对象是方法的调用者(实例对象) 2,被 static 修饰的方法,锁的对象就是 Class模板对象,这个则全局唯一 问题7: 一个普通同步方法,一个静 ...

  10. Golang 使用Protocol Buffer 案例

    目录 1. 前言 2. Protobuf 简介 2.1 Protobuf 优点 2.2 Protobuf 缺点 2.3 Protobuf Golang 安装使用 3. Protobuf 通讯案例 3. ...