在 Python 教程的这一章中,我们将讨论美妙且极其有用的功能“zip”。不幸的是,Python 的初学者经常被 zip 不必要地混淆和害怕。首先这个名字很混乱。许多人将 Python 的 zip 与众所周知的存档文件格式 ZIP 混淆,后者用于无损数据压缩。由于这种数据压缩不仅使所需的存储空间非常小,而且执行速度也非常快,因此选择了名称“zip”。在这种情况下,“zip”的意思是“迅速行动或迅速行动”。
Python 的“zip”与它完全无关。Python 中的 'zip' 功能基于英文单词 'zip' 的另一个含义,“用拉链关闭某物”。
我们将看到 zip 非常容易理解。但是,如果您想出使用 Python 帮助功能的想法,这将不适用。帮助文本肯定对此负有部分责任,并吓跑了新手:
Return a zip object whose .next() method returns a tuple where the i-th element comes from the i-th iterable argument. The .next() method continues until the shortest iterable in the argument sequence is exhausted and then it raises StopIteration.
这段文字是正确的,但很难理解。在我们尝试简化 zip 背后的理论之前,让我们从简单的例子开始。
我们将从两个列表开始并将 zip 应用到这两个列表:
a_couple_of_letters = [ "a" , "b" , "c" , "d" , "e" , "f" ]
some_numbers = [ 5 , 3 , 7 , 9 , 11 , 2 ]
print ( zip ( a_couple_of_letters , some_numbers ) )
输出:
结果是一个 zip 对象,如果您不了解 zip,那么您并不比以前更聪明。zip 的应用程序返回一个迭代器,它能够生成元组。它将每个可迭代对象(在我们的示例列表中)的第一项组合成一个元组,然后再组合第二项,依此类推。当其中之一用完时它会停止,即没有更多可用的项目。
查看它创建的内容的最佳方法是在 for 循环中使用它。
对于 t in zip ( a_couple_of_letters , some_numbers ):
打印( t )
输出:
('a', 5)
('b', 3)
('c', 7)
('d', 9)
('e', 11)
('f', 2)
如果你仔细观察上面的输出和下面的图片,你就会明白为什么 zip 与拉链有关,以及为什么他们选择了这个名字。
zip 可以有任意数量的可迭代参数,如下例所示:
位置 = [ “赫尔戈兰” , “基尔” ,
“柏林特格尔” , “康斯坦茨” ,
“霍恩派森贝格” ]
air_pressure = [ 1021.2 , 1019.9 , 1023.7 , 1023.1 , 1027.7 ]
温度 = [ 6.0 , 4.3 , 2.7 , - 1.4 , - 4.4 ]
海拔 = [ 4 , 27 , 37 , 443 , 977 ]
对于 t in zip (位置、 气压、 温度、 海拔):
打印(t )
输出:
('黑尔戈兰', 1021.2, 6.0, 4)
('基尔', 1019.9, 4.3, 27)
('柏林-泰格尔', 1023.7, 2.7, 37)
('康斯坦茨', 1023.1, -1.4, 443)
('Hohenpeißenberg', 1027.7, -4.4, 977)
zip 的使用不仅限于列表和元组。它可以应用于所有可迭代对象,如列表、元组、字符串、字典、集合、范围等等。
食品 = [ “火腿” , “垃圾邮件” , “奶酪” ]
为 项目 在 拉链(范围(1000 , 1003 ), 食物):
打印(项)
输出:
(1000,'火腿')
(1001, '垃圾邮件')
(1002, '奶酪')
让我们看看如果我们不带任何参数调用 zip 会发生什么:
for i in zip ():
打印(“这不会被打印” )
循环体没有被执行!
如果我们只用一个参数调用 zip 会发生什么,例如一个字符串:
s = "Python"
for t in zip ( s ):
打印( t )
输出:
('P',)
('y',)
('t',)
('H',)
('o',)
('n',)
所以这个调用创建了一个迭代器,它产生一个带有一个元素的元组,在我们的例子中是字符串的字符。
正如我们所见,可以使用任意数量的可迭代对象作为参数调用 zip。到目前为止,元素的数量或这些可迭代对象的长度是相同的。这是没有必要的。如果长度不同,则 zip 将在参数序列之一用完后立即停止生成输出。“停止产生输出”实际上意味着它会像所有其他迭代器一样引发 StopIteration 异常。这个异常被 for 循环捕获。您将在Python 教程的“迭代器和可迭代对象”一章中找到有关这种工作方式的更多信息。
以下示例是具有两个不同长度的列表的 zip 调用:
颜色 = [ “绿色” , “红” , “蓝” ]
汽车 = [ “宝马” , “阿尔法·罗密欧” ]
的 车, 颜色 以 拉链(汽车, 颜色):
打印(车, 颜色)
输出:
宝马绿色
阿尔法罗密欧红
我们有一份瑞士六个最大城市的清单。它由包含对、城市和人口数的元组组成:
cities_and_population = [( “苏黎世” , 415367 ), (
“日内瓦” , 201818 ), (
“巴塞尔” , 177654 ), (
“洛桑” , 139111 ), (
“伯尔尼” , 133883 ), (
“温特图尔” , 111851 ) ]
该任务包括创建两个列表:一个是城市名称,一个是人口数量。zip 是这个问题的解决方案,但我们还必须使用星号运算符来解压列表:
城市, 人口 = 名单(ZIP (* cities_and_population ))
印刷(市)
印刷(群)
输出:
(“苏黎世”、“日内瓦”、“巴塞尔”、“洛桑”、“伯尔尼”、“温特图尔”)
(415367, 201818, 177654, 139111, 133883, 111851)
这是需要的,例如,如果我们想绘制这些数据。以下示例仅用于说明目的。没有必要完全理解它。你必须熟悉Pandas。在下面的程序中,我们假设开始时只有组合列表可用:
进口 熊猫 作为 PD
cities_and_population = [( “苏黎世” , 415367 ), (
“日内瓦” , 201818 ), (
“巴塞尔” , 177654 ), (
“洛桑” , 139111 ), (
“伯尔尼” , 133883 ),
(“温特图尔" , 111851 )]
城市, 人口 = 列表( zip ( * city_and_population ))
s = pd. 系列(人口, 指数=城市)
s 。情节(种类= “酒吧” )
zip 还为我们提供了将两个可迭代对象转换为字典的绝佳机会。当然,前提是这些可迭代对象满足某些要求。应该用作键的可迭代对象必须是唯一的,并且只能由不可变对象组成。我们用以下莫尔斯电码示例演示了这一点。完整的摩尔斯电码字母表可以在我们关于字典的章节中找到:
abc = "abcdef"
morse_chars = [ ".-" , "-..." , "-.-." , "-.." , "." , “..-.” ]
text2morse = dict ( zip ( abc , morse_chars ))
打印( text2morse )
输出:
{'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.', 'F': '..-。'}
1数据来自 2020 年 4 月 1 日,不是开玩笑。位置是任意选择的。然而,有一个特殊的原因,为什么我选择了 Hohenpeißenberg。在 Hohenpeißenberg 上,我受邀为德国气象局教授两门令人难忘的 Python 课程:伟大的人和美妙的景色!