简体   繁体   English

在python中循环压缩列表

[英]Looping zipped list in python

I was toying around with the zip() function in python and discovered a problem while using the for loop. 我在python中使用zip()函数,并在使用for循环时发现了一个问题。 Here is my code: 这是我的代码:

list1 = ['monday', 'tuesday', 'wednesday', 'thursday']
list2 = [1, 2, 3, 4]

zipped_list = zip(list1, list2)

print(*zipped_list)  # unpacked zipped list

for a, b in zipped_list:   # for this to work comment the print(*zipped_list) statement
    print(a, b)

The output for this code is: 此代码的输出是:

('monday', 1) ('tuesday', 2) ('wednesday', 3) ('thursday', 4)

Process finished with exit code 0

Now if I remove the print(*zipped_list) statement then the for loop gets executed correctly: 现在,如果我删除print(* zipped_list)语句,那么for循环将被正确执行:

monday 1

tuesday 2

wednesday 3

thursday 4

Process finished with exit code 0

Why is this happening ? 为什么会这样?

As pointed out in the first comment, the zip object is consumed with the first print(*zipped_list) . 正如第一个注释中所指出的,zip对象与第一个print(*zipped_list) However, you can convert the zip object to a list first like so to be able to use the values of zip object again: 但是,您可以首先将zip对象转换为列表,以便能够再次使用zip对象的值:

zipped_list = list(zip(list1, list2))

A zip object is an Iterator . zip对象是Iterator This Q/A from the link should explain why this happens: 链接中的此Q / A应解释为什么会发生这种情况:

Q: When would I need an extra iterator? 问:我什么时候需要额外的迭代器?

A: Iterator will typically need to maintain some kind of position state information (like the index of the last element returned or the like). 答:迭代器通常需要维护某种位置状态信息(如返回的最后一个元素的索引等)。 If the iterable maintained that state itself, it would become inherently non-reentrant (meaning you could use it only one loop at a time). 如果iterable保持该状态本身,它将变得固有地不可重入(意味着你一次只能使用一个循环)。

Also take a look at the docs for zip . 另请查看zip文档。 Zip is equivalent to: Zip相当于:

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)

See the yield statement? 看到收益率表? This makes it a generator like object. 这使它成为像对象一样的生成器。 Hence looping over it once exhausts it. 因此,一旦耗尽它就会在它上面循环。 Note that just printing the zip object also exhausts it. 请注意,只打印zip对象也会耗尽它。

Since zip objects are generator like, they produce the elements on demand rather than expand an entire list into memory. 由于zip对象是生成器,因此它们按需生成元素,而不是将整个列表扩展到内存中。 The advantage this buys is greater efficiency in their typical use-cases. 这种购买的优势在于其典型用例的效率更高。

Shadowfax answered about the zip generator stuff. Shadowfax回答了关于zip生成器的事情。 If you were wondering why you have new lines... 如果你想知道为什么你有新线...

print(*zipped_list) # => print(elm1, elm2 ,elm3...) now newlines (only one in the end)

But like this: 但是像这样:

 for a, b in zipped_list:   
     print(a, b) # each print will do a newline in the end so you have many rows...

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

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