Python 在迭代时,zip和izip之间有什么功能上的区别吗?

Python 在迭代时,zip和izip之间有什么功能上的区别吗?,python,iterator,Python,Iterator,我有如下代码: for v1, v2 in zip(iter1, iter2): print len(v1) # prints 0 但当我将zip改为itertools.izip时,它会打印1 for v1, v2 in izip(iter1, iter2): print len(v1) # prints 1 其他代码都是一样的。我只是用izip替换了zip,它工作了。izip的输出是正确的 编辑:添加整个代码: #!/bin/python """ How to use: &g

我有如下代码:

for v1, v2 in zip(iter1, iter2):
   print len(v1) # prints 0
但当我将zip改为itertools.izip时,它会打印1

for v1, v2 in izip(iter1, iter2):
   print len(v1) # prints 1
其他代码都是一样的。我只是用izip替换了zip,它工作了。izip的输出是正确的

编辑:添加整个代码:

#!/bin/python

"""
How to use:
>>> from color_assign import Bag, assign_colors
>>> from pprint import pprint
>>> old_topics = set([
... Bag(name='T1', group=0, color=1, count=16000),
... Bag(name='T2', group=0, color=1, count=16000),
... Bag(name='T3', group=1, color=2, count=16000),
... Bag(name='T4', group=2, color=3, count=16000),
... ])
>>> new_topics = set([
... Bag(name='T1', group=0, color=None, count=16000),
... Bag(name='T2', group=4, color=None, count=16000),
... Bag(name='T3', group=1, color=None, count=16000),
... Bag(name='T4', group=1, color=None, count=16000),
... ])
>>> color_ranges = [ [1,10] ]
>>> assign_colors(old_topics, new_topics, color_ranges)
>>> pprint(sorted(new_topics, key=attrgetter('name')))
[Bag(name=T1, group=0, color=1, count=16000),
 Bag(name=T2, group=4, color=3, count=16000),
 Bag(name=T3, group=1, color=2, count=16000),
 Bag(name=T4, group=1, color=2, count=16000)]
>>> 
"""

from itertools import groupby, izip
from operator import attrgetter

class Bag:
  def __init__(self, name, group, color=None, count=None):
    self.name  = name 
    self.group = group
    self.color    = color   
    self.count  = count 
  def __repr__(self):
    return "Bag(name={self.name}, group={self.group}, color={self.color}, count={self.count})".format(self=self)
  def __key(self):
    return self.name
  def __hash__(self):
    return hash(self.__key())
  def __eq__(self, other):
    return type(self) is type(other) and self.__key() == other.__key()

def color_range_gen(color_ranges, used_colors):
  color_ranges = sorted(color_ranges)
  color_iter = iter(sorted(used_colors))
  next_used = next(color_iter, None)
  for start_color, end_color in color_ranges:
    cur_color = start_color
    end_color = end_color
    while cur_color <= end_color:
      if cur_color == next_used:
        next_used = next(color_iter, None)
      else:
        yield cur_color
      cur_color = cur_color + 1


def assign_colors(old_topics, new_topics, color_ranges):
  old_topics -= (old_topics-new_topics) #Remove topics from old_topics which are no longer present in new_topics
  used_colors = set()

  def group_topics(topics):
    by_group = attrgetter('group')
    for _, tgrp in groupby(sorted(topics, key=by_group), by_group):
      yield tgrp

  for topic_group in group_topics(old_topics):
    oldtset = frozenset(topic_group)
    peek = next(iter(oldtset))
    try:
      new_group = next(topic.group for topic in new_topics if topic.name == peek.name and not topic.color)
    except StopIteration:
      continue
    newtset = frozenset(topic for topic in new_topics if topic.group == new_group)
    if oldtset <= newtset:
      for topic in newtset:
        topic.color = peek.color
      used_colors.add(peek.color)

  free_colors = color_range_gen(color_ranges, used_colors)
  unassigned_topics = (t for t in new_topics if not t.color)
  for tset, color in zip(group_topics(unassigned_topics), free_colors):
    for topic in tset:
      topic.color = color

if __name__ == '__main__':
  import doctest
  doctest.testmod()
更新:
问题在于
groupby
在使用zip时使迭代器无效是的,它们的输出是相同的。唯一的区别是
zip
在内存中创建一个列表,而
izip
返回一个迭代器

>>> from itertools import izip

>>> zip(range(5), 'abcde')
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]

>>> it = izip(range(5), 'abcde')
>>> it
<itertools.izip object at 0xa660fcc>
>>> next(it)
(0, 'a')
>>> next(it)
(1, 'b')
>>来自itertools导入izip
>>>邮政编码(范围(5),“abcde”)
[(0,'a'),(1,'b'),(2,'c'),(3,'d'),(4,'e')]
>>>它=izip(范围(5),‘abcde’)
>>>它
>>>下一个(it)
(0,‘a’)
>>>下一个(it)
(1,‘b’)

请注意,
izip
在Python3中已被删除,
zip
在那里返回一个
iterator

您遇到的问题是由两个因素共同造成的。首先,
izip
仅根据需要推进底层迭代器,而
zip
需要立即获取所有项。其次,当一个
groupby
对象处于高级状态时:

返回的组本身是一个迭代器,它与
groupby()
共享底层iterable。因为源是共享的,所以当
groupby()
对象处于高级状态时,前面的组将不再可见。因此,如果以后需要该数据,则应将其存储为列表:


作为一个简单的修复,您可以更改
group\u主题
,在生成组之前调用其组上的
list

您的错误在其他地方。给我们看看。特别是,包括创建
iter1
iter2
,不要在应该使用
izip
的代码中调用
zip
@user2357112将可运行代码粘贴到testcase。如果您将zip更改为iziprelated,测试用例将通过:有人能发现这个bug吗?希望我的电脑没有问题。我想不出
for loop
是如何影响发电机的。我只更改for循环中的当前项。根本不引用循环的迭代。@balki:进一步分析了代码。见扩展答案。mera he+1 yad rakhiyo
>>> from itertools import izip

>>> zip(range(5), 'abcde')
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]

>>> it = izip(range(5), 'abcde')
>>> it
<itertools.izip object at 0xa660fcc>
>>> next(it)
(0, 'a')
>>> next(it)
(1, 'b')