简体   繁体   English

python 中的 [iter(list)]*2 是什么意思?

[英]what is meaning of [iter(list)]*2 in python?

I have found below code in web, result is tuple of two elements in list, how to understand [iter(list)]*2 ?我在 web 中找到了以下代码,结果是列表中两个元素的元组,如何理解[iter(list)]*2

lst = [1,2,3,4,5,6,7,8]
b=zip(*[iter(lst)]*2)
list(b)

[(1, 2), (3, 4), (5, 6), (7, 8)]

------------
[iter(lst)]*2
[<list_iterator at 0x1aff33917f0>, <list_iterator at 0x1aff33917f0>]

I check [iter(lst)]*2 , same iterator above, so meaning iter repeat double, so, if i check num from 2 to 3, result should be [(1, 2, 3), (4, 5, 6),(7,8,NaN)] but delete 7,8我检查[iter(lst)]*2 ,上面相同的迭代器,所以意味着iter重复双倍,所以,如果我检查 num 从 2 到 3,结果应该是[(1, 2, 3), (4, 5, 6),(7,8,NaN)]但删除 7,8

lst = [1,2,3,4,5,6,7,8]
b=zip(*[iter(lst)]*3)
list(b)
--------------
[(1, 2, 3), (4, 5, 6)]

iter(lst) turns a list into an iterator . iter(lst)将列表转换为迭代器 Iterators let you step lazily through an iterable by calling next() until the iterator runs out of items.迭代器让您可以通过调用next()来懒惰地通过一个可迭代对象,直到迭代器用完所有项。

[iter(lst)] puts the iterator into a single-element list. [iter(lst)]将迭代器放入一个单元素列表中。

[iter(lst)] * 2 makes 2 copies of the iterator in the list, giving [iter(lst)] * 2在列表中生成 2 个迭代器副本,给出

it = iter(lst)
[it, it] 

Both list elements are aliases of the same underlying iterator object, so whenever next() is called on either of the iterators as zip exhausts them, successive elements are yielded.两个列表元素都是同一个底层迭代器 object 的别名,因此每当在任一迭代器上调用next()时, zip耗尽它们,就会产生连续的元素。

*[...] unpacks the list of the two copies of the same iterator into the arguments for zip . *[...]将同一迭代器的两个副本的列表解压缩到 zip 的zip中。 This creates a zip object that lets you iterate through tuples of elements from each of its arguments.这将创建一个 zip object,它允许您从每个 arguments 中迭代元素的元组。

list(...) iterates through the zip object and copies the elements into a list. list(...)遍历 zip object 并将元素复制到列表中。 Since both zipped iterators point to the same underlying iterator, we get the sequential elements seen in your output.由于两个压缩迭代器都指向同一个底层迭代器,我们得到了 output 中看到的顺序元素。

Without using the iterator alias, you'd get不使用迭代器别名,你会得到

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

A similar way to write list(zip(*[iter(lst)] * 2)) is list(zip(lst[::2], lst[1::2])) , which seems a bit less magical (if much less performant).list(zip(*[iter(lst)] * 2))的类似方法是list(zip(lst[::2], lst[1::2])) ,这似乎不那么神奇(如果性能要差得多)。

The explanation for的解释

>>> list(zip(*[iter(lst)] * 3))
[(1, 2, 3), (4, 5, 6)]

omitting elements is that the first time the zip object tries to yield a None result on any of the argument iterables, it stops and does not generate a tuple.省略元素是 zip object 第一次尝试在任何参数迭代中产生None结果时,它停止并且不生成元组。 You can use itertools.zip_longest to match your expected behavior, more or less:您可以使用itertools.zip_longest或多或少地匹配您的预期行为:

>>> list(zip_longest(*[iter(lst)] * 3))
[(1, 2, 3), (4, 5, 6), (7, 8, None)]

See the canonical answer List of lists changes reflected across sublists unexpectedly if the [...] * 2 aliasing behavior is surprising.如果[...] * 2别名行为令人惊讶,请参阅规范答案列表更改反映在子列表中意外

Quite a tricky construct to explain.一个相当棘手的结构来解释。 I'll give it a shot:我试一试:

with [iter(lst)] you create a list with with one item.使用[iter(lst)]您可以创建一个包含一个项目的列表。 The item is an iterator over a list.该项目是列表的迭代器。

whenever python tries to get an element from this iterator, then the next element of lst is returned until no more element is available.每当 python 尝试从此迭代器获取元素时,就会返回lst的下一个元素,直到没有更多元素可用为止。

Just try following:只需尝试以下操作:

i = iter(lst)
next(i)
next(i)

the output should look like: output 应如下所示:

>>> lst = [1,2,3,4,5,6,7,8]  
>>> i = iter(lst)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)
4
>>> next(i)
5
>>> next(i)
6
>>> next(i)
7
>>> next(i)
8
>>> next(i)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Now you create a list that contains twice exactly the same iterator.现在您创建一个包含两次完全相同的迭代器的列表。 You do this with itlst = [iter(lst)] * 2你可以用itlst = [iter(lst)] * 2

try out following:尝试以下:

itlst1 = [iter(lst)] * 2
itlst2 = [iter(lst), iter(lst)]
print(itlst1)
print(itlst2)

The result will look something like:结果将类似于:

>>> itlst1 = [iter(lst)] * 2
>>> itlst2 = [iter(lst), iter(lst)]
>>> print(itlst1)
[<list_iterator object at 0x7f9251172b00>, <list_iterator object at 0x7f9251172b00>]
>>> print(itlst2)
[<list_iterator object at 0x7f9251172b70>, <list_iterator object at 0x7f9251172ba8>]

What is important to notice is, that itlst1 is a list containing twice the same iterator, whereas itlst2 contains two different iterators.需要注意的重要一点是, itlst1是一个包含两次相同迭代器的列表,而itlst2包含两个不同的迭代器。

to illustrate try to type:为了说明尝试输入:

next(itlst1[0])
next(itlst1[1])
next(itlst1[0])
next(itlst1[1])

and compare it with:并将其与:

next(itlst2[0])
next(itlst2[1])
next(itlst2[0])
next(itlst2[1])

The result is:结果是:

>>> next(itlst1[0])
1
>>> next(itlst1[1])
2
>>> next(itlst1[0])
3
>>> next(itlst1[1])
4
>>> 
>>> next(itlst2[0])
1
>>> next(itlst2[1])
1
>>> next(itlst2[0])
2
>>> next(itlst2[1])
2

Now to the zip() function ( https://docs.python.org/3/library/functions.html#zip ):现在到zip() function ( https://docs.python.org/3/library/functions.html#zip ):

Try following:尝试以下操作:

i = iter(lst)
list(zip(i, i))

zip() with two parameters. zip()有两个参数。 Whenver you try to get the next element from zip it will do following:当您尝试从zip获取下一个元素时,它将执行以下操作:

  • get one value from the iterable that is the first parameter从作为第一个参数的可迭代对象中获取一个值
  • get one value from the iterable that is the second parameter从作为第二个参数的可迭代对象中获取一个值
  • return a tuple with these two values.返回具有这两个值的元组。

list(zip(xxx)) will do this repeatedly and store the result in a list. list(zip(xxx))将重复执行此操作并将结果存储在列表中。

The result will be:结果将是:

>>> i = iter(lst)
>>> list(zip(i, i))
[(1, 2), (3, 4), (5, 6), (7, 8)]

The next trick being used is the * that is used to use the first element as first parameter to a function call, the second element as second parameter and so forth) What does ** (double star/asterisk) and * (star/asterisk) do for parameters?使用的下一个技巧是*用于将第一个元素用作 function 调用的第一个参数,第二个元素作为第二个参数等等) **(双星号/星号)和 *(星号/星号)的作用) 做参数?

so writing:所以写:

itlst1 = [iter(lst)] * 2
list(zip(*itlst1))

is in this case identical to在这种情况下与

i = iter(lst)
itlst1 = [i] * 2
list(zip(itlst1[0], itlst[1]))

which is identical to这与

list(zip(i, i))

which I explained already.我已经解释过了。

Hope this explains most of the above tricks.希望这可以解释上述大部分技巧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM