一篇文章把握 Python 内嵌 zip() 的所有内容

zip() 是 Python 中最好用的内嵌种类之一 ,它能够接受好几个可迭代更新目标主要参数,再回到一个迭代器,能够把不一样可迭代更新目标的原素组成起來。

我以前写迭代器系列产品的情况下 ,在《Python进阶:设计模式之迭代器模式》中简易地详细介绍过它,前几日汉语翻译了 Python 3.10 听取意见的 PEP-618 ,详细介绍了它可能迈入的变动 。

可是 ,也有许多 同学们并不了解 zip() ,或是不可以灵活运用它的用法,因而文中准备来做一个更加详尽的整理。

內容关键分三一部分:

  • 用法一部分:详细介绍它的基本用法 、高級用法、骚操作用法
  • 升阶一部分:详细介绍它的完成基本原理,关心好多个完成的关键点
  • 散发一部分:聚焦点它的不够 ,及其解决方案

1、zip() 的 n 种用法

基础用法:像拉锁一样,将好几个可迭代更新目标组成起來,随后可以用 for 循环系统先后取下 ,或是一次性将結果存进列表 、元组或是字典这类的器皿中。

它的結果是一个迭代器,迭代器转化成的原素是元组,第 i 个元组的原素各自来源于可迭代更新目标主要参数的第 i 个原素 ,如圖所显示 。

此外,for 循环系统还能够把元组内的原素先后取下,那样会很便捷:

它的主要参数并不规定是同一类的可迭代更新目标 ,因而能够有十分多的组成方法,比如:

可是,假如把字典做为 zip() 的主要参数 ,会是啥结果呢?字典是 key-value 键值对方式 ,跟列表这类的单一原素构造不一样。

试验一下,能够看得出,zip() 默认设置总是解析xml字典的 key 值:

假如要想取下字典的 value 值 ,或是取下 key-value 键值对,那麼能够应用字典内置的解析xml方式 values() 和 items():

应用 zip(),还能够较为便捷地对二维列表完成行列转换:

上例中的星号(*)操作符能够解压工具(unpacking) ,将要 my_list 的原素(也是列表)解成好几个主要参数给 zip(),进而将 3 个列表重新排列。

解压工具操作符针对 zip 目标一样可用,由于 zip() 自身是一次行列转换的实际操作 ,若将它解压工具后做为主要参数给 zip(),相当于再做一次行列转换,也就是返回了起点(除开最终的結果是元组):

最终再详细介绍一种用法:建立 n*n 的矩阵 ,每列的数据同样 。

2、zip() 的基本原理分析

官方网文本文档中得出了 zip() 的 Python 伪代码(并不是是 Python 编译器内嵌的完成,只以便展现基础的编码逻辑性):

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    sentinel = object()
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            elem = next(it, sentinel)
            if elem is sentinel:
                return
            result.append(elem)
        yield tuple(result)

在这里段简洁明了的编码中,能够剖析出几个方面重要的信息内容:

  • zip 接受可变性总数的可迭代更新目标主要参数 ,这种主要参数会历经 iter() 解决成迭代器 。推理:若出現非可迭代更新目标 ,这里会出错
  • while 循环系统在分辨列表是不是为空,而列表中的原素是将主要参数转换而成的迭代器。推理:若入参存有合理的可迭代更新目标,则 while 循环系统自始至终为真;若沒有入参 ,则什么事都不做
  • next() 会先后载入迭代器中的下一个原素,它的第二个主要参数会做为迭代器耗光时的返回值。推理:每一轮先后取下这种迭代器的一个原素,当某一迭代更新被耗光时 ,则撤出无限循环,这就代表着未耗光的迭代器会被立即放弃

3、zip() 的难题与处理

zip() 最显著的难题是它会放弃掉未耗光的迭代器:

它是一种木桶效应,最后的結果由最少的木工板来决策 。

有一种处理构思是取长板 ,另外补充薄弱点(用 None 值添充),这就是 itertools 中的 zip_longest 方式 :

它添充了数据冗余数据信息,另外最大限度地确保了原始记录的一致性。

可是 ,如果我们不期待有数据冗余数据信息,只期待获得按最多方法两端对齐的数据信息呢?

Python 官方网近期听取意见了 PEP-618,它便是以便解决这个问题。当出現迭代器长短不一致时 ,它既不向薄弱点让步 ,都不向长板让步,只是抛出去 ValueError 。它觉得入参值不正确,也就是严格管理入参的数据库安全。

该 PEP 会被合入到一年后的 Python 3.10 版本号 ,有关大量的內容关键点,可查看这篇PEP-618 译文翻译 。


微信公众号:Python猫

今日头条号:Python猫

知乎问答:豌豆花下猫

开拓者:豌豆花下猫

本文版权归趣快排SEO www.SeogurUblog.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ▶61910465