本文授权转载自机器学习算法与Python挖掘禁止二次转载大家好,我是老表阅读文本大概需要 9分钟zip()的作用 先看一下语法:zip(iter1 [,iter2 [...]]) —&...
本文授权转载自机器学习算法与Python挖掘
禁止二次转载
大家好,我是老表
阅读文本大概需要 9分钟

zip()的作用

先看一下语法:
zip(iter1 [,iter2 [...]]) —> zip object
Python的内置help()模块提供了一个简短但又有些令人困惑的解释:
返回一个元组迭代器,其中第i个元组包含每个参数序列或可迭代对象中的第i个元素。当最短的可迭代输入耗尽时,迭代器将停止。使用单个可迭代参数,它将返回1元组的迭代器。没有参数,它将返回一个空的迭代器。
与往常一样,当您精通更一般的计算机科学和Python概念时,此模块非常有用。但是,对于初学者来说,这段话只会引发更多问题。让我们尝试通过示例,代码片段和可视化来解释zip()功能:从许多迭代中获取元素,然后…… 放在一起
我们可以通过几个列表来演示zip()的功能:
uppercase = ['A', 'B', 'C'] lowercase = ['a', 'b', 'c'] for x, y in zip(uppercase, lowercase): print(x, y)
输出:
A a B b C c
但是,不限于两个可迭代对象作为参数传递-我们可以添加任意多个:
uppercase = ['A', 'B', 'C'] lowercase = ['a', 'b', 'c'] numbers = [1, 2, 3] for x, y, z in zip(uppercase, lowercase, numbers): print(x, y, z)
这将输出:
A a 1 B b 2 C c 3
让我们直观地看一下该zip()函数在Python中的工作方式:
zip()函数的另一个重要警告是如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同:
uppercase = ['A', 'B', 'C', 'D', 'E'] lowercase = ['a', 'b', 'c', 'd'] numbers = [1, 2, 3] for x, y, z in zip(uppercase, lowercase, numbers): print(x, y, z)
输出:
A a 1 B b 2 C c 3
正如我们所看到的,即使列出了三个三元组,uppercase和lowercase列表具有5和4个元素。
要知道的重要一件事是zip()函数返回什么。
尽管似乎在调用此函数时会得到一个列表,但实际上它返回一个称为zip object的特殊数据类型,这意味着使用索引将无法浏览,下面我们学习如何将其转换为其他数据类型(例如列表)。
在此之前,我们还应再来学习一下迭代(Iteration)、迭代器对象(iterable)、迭代器(iterator )的概念:
Iteration是计算机科学的通用术语。它是指对一组元素执行一项操作,一次执行一个元素。一个很好的例子是循环 -它适用于每个单独的项目,直到整个项目集运行完毕为止。
Iterable是可以遍历的对象(译者注:在Python中所有东西都是object, 比如说变量,容器,类),iterable是可以产生iterator的object。
iterator是表示数据流的对象,它一次返回一个元素的数据。它还会记住其在迭代过程中的位置。本质上,它控制应如何迭代可迭代对象。

将zip()对象转换为列表(并使用索引)

zip()函数返回一个zip对象(类似于map()操作方式)。
zip对象提供了一些有趣的功能(迭代速度比list更快),但是我们经常需要将其转换为list。为了做到这一点,我们需要调用list()函数:
b = ["red", "green", "blue"] c = ["leopard", "cheetah", "jaguar"] print(list(zip(b, c)))
输出:
[('red', 'leopard'), ('green', 'cheetah'), ('blue', 'jaguar')]
list()函数将zip对象转换为一个元组列表。我们可以使用索引浏览各个元组。出于可读性考虑,我们首先将新列表分配给一个变量:
b = ["red", "green", "blue"] c = ["leopard", "cheetah", "jaguar"] new_list = list(zip(b, c)) print(new_list[0]) print(new_list[1]) print(new_list[2])
这将输出:
('red', 'leopard') ('green', 'cheetah') ('blue', 'jaguar')

将zip()对象转换成字典

另外,该dict()函数可用于将zip对象转换为字典。需要注意的是,只能使用两个zip()参数-前者产生key,后者产生value:
b = ["red", "green", "blue"] f = ["strawberry", "kiwi", "blueberry"] print(dict(zip(b, f)))
输出:

解压列表

在某些情况下,我们需要执行相反的操作——解压迭代器。解压操作涉及将压缩后的元素恢复为其原始状态。为此,我们添加*运算符到函数调用中。例:
a = [1, 2, 3] b = [4, 5, 6] zipped = zip(a, b) list(zipped) a2, b2 = zip(*zip(a, b)) print(a == list(a2) and b == list(b2))
输出:
True

Zip与列表生成式(for循环潜在问题)

zip()函数与Python中的for循环一起使用的可视化
在应用for循环后注意缺少的元素!
Python的另一个很棒的功能——列表推导式,可以与zip()函数结合使用。表面上看起来很简单……
m = ["mind", "mouse", "mini"] n = ["norm", "night", "necklace"] [print(a, b) for a, b in zip(m, n)]
输出:
mind norm mouse night mini necklace
看起来很简单,似乎没有任何错误,对吗?是的
如果我们想a从列表生成式获取参数并打印出来,我们得到a NameError的报错提示,这是完全正常的,因为a在列表推导之外不是实数:
Traceback (most recent call last): File "C:\Pro\Py\tp-ex\tmp1.py", line 5, in print(a) NameError: name 'a' is not defined
但是,如果我们决定使用for循环而不是列表生成式,然后打印a,我们会得到一些奇怪的结果。请记住,for循环输出的结果与列表生成式的结果相同。
m = ["mind", "mouse", "mini"] n = ["norm", "night", "necklace"] for m, n in zip(m, n): print(m, n) print(m)
结果输出是…
mind norm mouse night mini necklace mini
等等,叛逆的mini在这里干什么?事实证明,m先前引用的列表变量"mind", "mouse", "mini"被覆盖了!因此,应该牢记列表生成式和for循环的运行方式完全不同。

结论

事实证明,zip()函数在 Python 中确实有一些窍门!????与往常一样,鼓励大家实际使用我们的代码示例,而不仅是阅读本文。如果您与代码进行交互并对其进行调整,则肯定会遇到一些独特的问题-解决它们将帮助大家更好地掌握知识。
原文:https://blog.soshace.com/python-zip-function-explained-and-visualized/
ByDenis Kryukov
大家好,我是老表
觉得本文不错的话,转发、留言、点赞,是对我最大的支持。
每日留言
说说你读完本文感受?
或者一句激励自己的话?
或对2019的总结?
(字数不少于15字)
想进学习交流群
加微信:jjxksa888
备注:简说Python
你的城市下雪❄️没?
2小时快速掌握Python基础知识要点。
完整Python基础知识要点
作为一个Python初学者,昨天在实践书上一个实例时遇到了zip()和*zip()函数,而书中恰好对这两个函数没有过多的解释(这两个函数其实是同一个函数),网上搜索后对zip()倒是弄明白了,但是对*zip()的说法,CSDN上大...
作为一个Python初学者,昨天在实践书上一个实例时遇到了zip()和*zip()函数,而书中恰好对这两个函数没有过多的解释(这两个函数其实是同一个函数),网上搜索后对zip()倒是弄明白了,但是对*zip()的说法,CSDN上大部分人却是说其是zip()的逆操作云云,但是操作下来感觉完全不是一回事,后来又搜了几个不同的文章,结合自己的代码操作后才完全把这个事情弄明白,所以将其记录下来,方便自己的同时也看看能不能帮助到同样有疑惑的Python初学者们。
首先说结论:

1. zip()和*zip()是同一个函数,而非后者是前者的逆操作,两者操作结果不同的原因主要是因为星号*的存在

2. 通俗的说,倒不如说zip()是压缩操作,而*星号是解压缩操作,* 才是zip()的逆操作

下面简述zip()函数并用coding来说明我的结论:
Zip():
作用:压缩数组,把多个列表压缩成多个多元元素(ps.这里的几元元素指的是一个元素里有几个值,如果我的说法不准确或者错用了名词,欢迎大家指正我)
特性:
1. 当操作数之间长度不一致时,其长度与最短操作数的长度一致
a = [1,2,3] b = [4,5,6,7] c = [4,5,6,7,8] zipped = zip(a,b,c) print(*zipped) = (1, 4, 4) (2, 5, 5) (3, 6, 6)
a, b, c的长度分别为3,4,5,最后zipped的长度为3,把三个列表压缩成了3个三元元素,(为什么这里输出时要加个*号呢,请大家往下看)
2. 在python3中,zip()函数返回的值是一个迭代器,这个迭代器表示的是数据存储在内存中的哪个位置,而不能直接进行访问/输出/使用,需要用list,for循环或者*号解压后才能正常显示。
print(zipped) print(list(zipped)) print(*list(zipped)) #输出分别为[(1, 4, 4), (2, 5, 5), (3, 6, 6)] (1, 4, 4) (2, 5, 5) (3, 6, 6)
此时我们分别对比输出结果,反应快的朋友可能已经发现了,*号的存在使得输出结果“少了一层”,从一个由“三个元组组成的列表”变成了“三个元组”(ps.元组就是组内元素不可改变的列表)。
所以也可以说,*号让一个二维列表变成了多个一维元组。所以当我简单的print(*zipped)时,星号的作用是把zipped的“迭代器”格式解了一层,把它变成了可以打印出来的“数据格式”,接下来我会在下面用coding再次简述一下*号。

注意:有时候你可能会发现,你输出完zipped后,想再次输出时,列表里为空了。这是因为,zip()在python3中返回一个迭代器,你只能在迭代器迭代一次,用完后元素虽然不会消失,但再次迭代会得到0个元素,除zip外,map,filter也是如此,因为python就是这么规定的。

*号的特性:对操作数进行“解压“
a = 5 b = [3,4,5] c = [(3,4,5), (6,7,8)] d = [[(3,4,5),(6,7,8)]] --- print(*a) #结果会出现error print(*b) print(*c) print(*d) #输出分别为 Error 3 4 5 (3, 4, 5) (6, 7, 8) [(3, 4, 5), (6, 7, 8)]
可以发现,*号把所有操作数都解压了一层,二维列表变成了一维,三维变成了二维,而对int进行解压报错时,错误提示为
print() argument after * must be an iterable, not int
*号后必须为迭代器,而不能是int类型的值
可以简单理解为int已经是“数据基础格式”了,不能再进行解压缩了
简述完zip()和*号,接下来就是最后的zip(*zip(a,b))及利用zip进行矩阵运算。
很多人说*zip()是zip()的逆操作,但是当他们展示code时,却往往写的是zip(*zip(a,b))(CSDN上超过一半的人对zip(), *zip()都是这样说的,直至我搜关于*星号的文章后才恍然大悟)按照这个逻辑,其实应该是*zip(zip(a,b))才对,因为根据函数嵌套,总是先运行括号内的,zip(*zip(a,b))不就变成“先解压缩再进行压缩”了?
然而,*zip(zip(a,b))后,输出的结果并不是预想中的结果,反而m,n = zip(*zip(a,b))输出的结果才是原来的结果,这是为什么呢?
1. *zip(zip(a,b))
首先说一下,当zip后只有一个列表时,他会进行迭代操作,把这个列表和元素为0的空列表进行迭代,所以当zip的操作数只有一个时,程序并不会报错。
a = [1,2,3] zipped = zip(a) print(list(zipped)) = [(1,), (2,), (3,)]a = [1,2,3] b = [4,5,6,7] zipped = zip(a,b) #此时zipped中数据为(1,4) (2,5) (3,6) zippeded = zip(zipped) #再调用一次zip print(*zippeded) = ((1, 4),) ((2, 5),) ((3, 6),) #简直和原来的a,b大相径庭
2. m,n = zip(*zip(a,b))
m = [1, 2, 3] n = [4, 5, 6] print("zip(m, n)返回:", list(zip(m, n))) print("*zip(m, n)返回:", *zip(m, n)) m2, n2 = zip(*zip(m, n)) print("m2和n2的值分别为:", m2, n2) #输出结果为 zip(m, n)返回: [(1, 4), (2, 5), (3, 6)] *zip(m, n)返回: (1, 4) (2, 5) (3, 6) m2和n2的值分别为: (1, 2, 3) (4, 5, 6)
虽然括号不一样了,从一开始的[ ]变成了后面的( ),但是既然元组是元素不可变的列表,两者的值其实都是一样的,进一步拆解一下:
#因为*zip(m,n)返回值为(1,4) (2,5) (3,6),此时再对其zip一遍,是不是等效于下面的代码了 _1 = (1,4) _2 = (2,5) _3 = (3,6) m1,m2 = zip(_1,_2,_3) #分别把结果的2个元素赋给m1和m2,所以又还原成了(1,2,3) (4,5,6)
所以,并不是*zip()是逆操作,而是又进行了一次zip()操作,把列表转置回来了。
因此,zip()也可用于进行矩阵运算,当你进行一次zip时,横坐标和纵坐标调换了一次,这在矩阵乘法中很常见,而使用2次zip操作,则又把横纵坐标调换回来了,或许这也是各位CSDN作者只从结果看,又看到zip()和*zip()这两个看起来如此对仗的操作,便把两者当成互逆操作的原因吧,其实*在其中的作用只是解压了第一次zip后的迭代器格式,把其转换成数据格式罢了。
带*号变量严格来说并不是一个变量,在解压后,它其实是一个参数,一个数据,它不能作为一个变量而被赋值,但可以作为参数传递。正如你不能对int数1,2,3,4,5赋值一样
洋洋洒洒写了不少,希望能帮助到大家,如果我的文章中有什么错误或者不准确的地方,也欢迎大家勘误,大家共同学习。
Python内置函数Python abs()函数Python all() 函数Python any() 函数Python basestring() 函数Python bin() 函数Python bool() 函数Python bytearray() 函数Python callable() 函数Python chr() 函数Python ...
Python abs()函数
描述:
abs() 函数返回数字的绝对值。
abs() 方法的语法:
abs( x )
参数:
x – 数值表达式。
返回值:
函数返回x(数字)的绝对值。
实例:
print "abs(-45) : ", abs(-45) print "abs(100.12) : ", abs(100.12) print "abs(119L) : ", abs(119L)
输出结果:
abs(-45) : 45 abs(100.12) : 100.12 abs(119L) : 119
Python all() 函数
描述:
all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 True,如果是返回 True,否则返回 False。
元素除了是 0、空、None、False 外都算 True。
以下是 all() 方法的语法:
all(iterable)
参数:
iterable – 元组或列表。
返回值:
如果iterable的所有元素不为0、’’、False或者iterable为空,all(iterable)返回True,否则返回False;
注意:空元组、空列表返回值为True,这里要特别注意。
all(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0 True all(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素 False all([0, 1,2, 3]) # 列表list,存在一个为0的元素 False all(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0 True all(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素 False all((0, 1, 2, 3)) # 元组tuple,存在一个为0的元素 False all([]) # 空列表 True all(()) # 空元组 True
Python any() 函数
描述:
any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
元素除了是 0、空、False 外都算 True。
any() 方法的语法:
any(iterable)
参数:
iterable – 元组或列表。
返回值:
如果都为空、0、false,则返回false,如果不都为空、0、false,则返回true。
实例:
any(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0 True any(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素 True any([0, '', False]) # 列表list,元素全为0,'',false False any(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0 True any(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素 True any((0, '', False)) # 元组tuple,元素全为0,'',false False any([]) # 空列表 False any(()) # 空元组 False
Python basestring() 函数
描述:
basestring() 方法是 str 和unicode 的超类(父类),也是抽象类,因此不能被调用和实例化,但可以被用来判断一个对象是否为 str 或者 unicode 的实例,isinstance(obj, basestring) 等价于 isinstance(obj, (str, unicode))。
basestring() 方法的语法:
basestring()
参数:
无
返回值:
无
实例:
isinstance("Hello world", str) True isinstance("Hello world", basestring) True
Python bin() 函数
描述:
bin() 返回一个整数 int 或者长整数 long int 的二进制表示。
bin() 方法的语法:
bin(x)
参数:
x – int 或者 long int 数字
返回值:
字符串
实例:
bin(10) '0b1010' bin(20) '0b10100'
Python bool() 函数
描述:
bool() 函数用于将给定参数转换为布尔类型,如果没有参数,返回 False。
bool 是int 的子类。
bool() 方法的语法:
class bool([x])
参数:
x – 要进行转换的参数。
返回值:
返回 Ture 或False。
实例:
bool() False bool(0) False bool(1) True bool(2) True issubclass(bool, int) # bool 是int 子类 True
Python bytearray() 函数
描述:
bytearray() 方法返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0