whx_py 发表于 2022-10-15 20:41:07

不理解代码的含义 list(zip(*[iter([1, 2, 3, 4, 5, 6, 7, 8, 9])] * 3))

浏览论坛看到的一篇小甲鱼发布的问题,还是有点不理解。原链接 https://fishc.com.cn/thread-140340-1-1.html

首先是拆解开的答案:

>>> x = iter()
>>> list(zip(x, x, x))

第2行的zip(x,x,x)不太理解。是指第一个x为iter(),取出了"1";第二个x为iter(),取出了"2",一直到最后吗?



然后是最后的答案:

>>> list(zip(*)] * 3))
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]

第一个"*"是什么意思,如果可以的话再告诉我是具体哪节课的知识点。然后第一个"*"的的运算是晚于"*3"的,对吧?




第一次发帖,希望来个好人帮帮忙,谢谢了。

Brick_Porter 发表于 2022-10-16 11:53:52

第一个x为iter(),取出了"1";第二个x为iter(),取出了"2",一直到最后吗?
答案是肯定的,确实如你所理解的那样。具体过程还是分步骤拆解来理解吧。

首先看最里层的iter(),这是在调用iter把列表转为迭代器;

然后是)]*3,首先把上一步生成的迭代器组成一个列表,然后*3就是把列表中的元素拷贝为3份,此时列表中的元素是三个相同的迭代器,类似这样:), iter(), iter()]。切记,这个列表中的三个迭代器是完全相同的;

接下来是*), iter(), iter()]。正如你预期的那样,列表前面的这个星号运算优先级确实低于乘号,作用是解包。解包之前列表中的所有元素构成了一个整体,解包后成为一个个独立的元素。此处之所以要解包是为了把上个步骤中列表的三个迭代器都传给zip。来看看加不加这个解包用的星号的区别吧:
>>> x = iter()
>>> y =
>>> zip(*y)# 等价于zip(x, x, x)
>>> zip(y)# 等价于zip()

最后list从zip(x, x, x)中取值并组成一个列表,zip每次返回的都是一个元组,所以你可以看到列表中的每个元素都是包含三个数字的元组。
之所以每个元组都有三个数字,是因为zip把传入的三个迭代器iter()进行对齐处理,每次都从这三个迭代器中各取一个数字组成一个元组,并且把这个元组给到list。
为什么1,2,3是一个元组,4,5,6又是另外一个元组呢?前面解释列表拷贝操作的时候说过了,列表中的三个迭代器其实是同一个对象的三个副本,它们完全相同!所以表面上看zip每次从三个迭代器中取出一个值,可实际效果却是从同一个迭代器中一次取三个值,如此一来列表就恰好被分成了三份了。这是背后的原理

whx_py 发表于 2022-10-16 20:27:59

Brick_Porter 发表于 2022-10-16 11:53
答案是肯定的,确实如你所理解的那样。具体过程还是分步骤拆解来理解吧。

首先看最里层的iter(

嗯嗯,大佬讲的很明白,感谢大佬。我还有个想确认的问题是:因为x是迭代器,所以zip(x,x,x)每次只依次取x的一个值,所以才有(1,2,3)(4,5,6)(7,8,9),而不是同时取值得到(1,1,1)(2,2,2)这样,是可以这样理解的对吗?

Brick_Porter 发表于 2022-10-16 21:17:57

本帖最后由 Brick_Porter 于 2022-10-16 21:34 编辑

whx_py 发表于 2022-10-16 20:27
嗯嗯,大佬讲的很明白,感谢大佬。我还有个想确认的问题是:因为x是迭代器,所以zip(x,x,x)每次只依次取x ...

虽然只有一行代码,但是背后的逻辑其实挺复杂的。
每一次zip(x, y, z)都会分别从x、y、z中取一个值,组成一个元组,然后返回这个元组。所以其实我们期望的结果应该是(1, 1, 1)、(2, 2, 2)……这样的,但是我们的代码zip(x, x, x)中的三个x是完全相同的,换言之它们就是同一个迭代器对象,而zip每次又要返回3个元素组成的元组。由于这个巧合的存在所以实际输出为(1, 2, 3)、(4, 5, 6)……

zip是一个类,用来“压缩”多个可迭代对象,所谓的压缩就是我前面说的“对齐”,注意看下面的代码:
>>> x =
>>> y = ('a', 'b', 'c', 'd')
>>> z =
>>> result = zip(x, y, z)# 尽管x、y、z三个对象长度不等也可以对齐,按照最短的来处理
>>> for i in result:
>>>   print(i)
(1, 'a', True)
(2, 'b', False)
(3, 'c', False)当你需要同时处理多个可迭代对象的时候就可以用到zip了

iter其实也是一个类而不是函数,它的作用也挺复杂的,因为它的关系导致了最后的输出结果为(1, 2, 3)、(4, 5, 6)……iter也是个黑魔法,如果还有疑问请留言

whx_py 发表于 2022-10-17 16:03:49

Brick_Porter 发表于 2022-10-16 21:17
虽然只有一行代码,但是背后的逻辑其实挺复杂的。
每一次zip(x, y, z)都会分别从x、y、z中取一个值, ...

感谢,完全明白了{:5_110:}
页: [1]
查看完整版本: 不理解代码的含义 list(zip(*[iter([1, 2, 3, 4, 5, 6, 7, 8, 9])] * 3))