我在python中使用zip()函数,并在使用for循环时发现了一个问题。 这是我的代码:
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)
此代码的输出为:
('monday', 1) ('tuesday', 2) ('wednesday', 3) ('thursday', 4)
Process finished with exit code 0
现在,如果我删除了print(* zipped_list)语句,那么for循环就会正确执行:
monday 1
tuesday 2
wednesday 3
thursday 4
Process finished with exit code 0
为什么会这样?
答案 0 :(得分:5)
正如第一条评论中所指出的,zip对象与第一条print(*zipped_list)
一起使用。但是,您可以首先将zip对象转换为列表,以便能够再次使用zip对象的值:
zipped_list = list(zip(list1, list2))
zip对象是Iterator
。链接中的这个Q / A应该解释为什么会发生这种情况:
问:我什么时候需要额外的迭代器?
答:迭代器通常需要保持某种位置 状态信息(如返回的最后一个元素的索引或 喜欢)。如果可迭代维持该状态本身,那么它将成为 本质上不可重入(意味着你只能在一个循环使用它 时间)。
另请查看zip的文档。 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)
参见收益率表?这使它成为像对象一样的生成器。因此,一旦耗尽它就会在它上面循环。请注意,只打印zip对象也会耗尽它。
由于zip对象是生成器,因此它们按需生成元素,而不是将整个列表扩展到内存中。这种购买的优势在于其典型用例的效率更高。
答案 1 :(得分:1)
Shadowfax回答了关于zip生成器的事情。 如果你想知道为什么你有新线......
print(*zipped_list) # => print(elm1, elm2 ,elm3...) now newlines (only one in the end)
但是像这样:
for a, b in zipped_list:
print(a, b) # each print will do a newline in the end so you have many rows...