【问题标题】:Python enumerate inside for loop skips alternate itemsPython enumerate inside for 循环跳过备用项目
【发布时间】:2013-11-23 11:50:38
【问题描述】:

我有一种情况,类外的 for 循环似乎与类内的枚举交互。

示例代码:

class MyContainerClass(object):
    def __init__(self):
        self.collection = []
    def __str__(self):
        return (len(self.collection) == 0 and 'Empty' or
                ', '.join(str(item) for item in self.collection))
    def __iadd__(self,item):
        print "adding {item}".format(item=str(item))
        self.collection.append(item)
        return self
    def __iter__(self):
        return iter(self.collection)
    def discard(self,item):
        print "discarding {item}".format(item=str(item))
        for index, value in enumerate(self.collection):
            if value == item:
                print "found {value}=={item}".format(value=value,item=item)
                return self.collection.pop(index)
        return False

class MyItemClass(object):
    def __init__(self,value):
        self.value=value
    def __str__(self):
        return '{value}'.format(value=self.value)
    def __eq__(self,other):
        if self.value == other.value:
            return True
        else:
            return False

c1 = MyContainerClass()
c2 = MyContainerClass()

c2 += MyItemClass('item1')
c2 += MyItemClass('item2')
c2 += MyItemClass('item3')
c2 += MyItemClass('item4')
c2 += MyItemClass('item5')
print "c1 is : {c1}".format(c1=str(c1))
print "c2 is : {c2}".format(c2=str(c2))

for item in c2:
    print "for got {item}".format(item=str(item))
    c1 += c2.discard(item)

print "c1 is : {c1}".format(c1=str(c1))
print "c2 is : {c2}".format(c2=str(c2))

产生这个输出:

adding item1
adding item2
adding item3
adding item4
adding item5
c1 is : Empty
c2 is : item1, item2, item3, item4, item5
for got item1
discarding item1
found item1==item1
adding item1
for got item3
discarding item3
found item3==item3
adding item3
for got item5
discarding item5
found item5==item5
adding item5
c1 is : item1, item3, item5
c2 is : item2, item4

我确信这很明显,可能与 iter 函数有关,但我目前看不到。

【问题讨论】:

    标签: python for-loop enumerate


    【解决方案1】:

    您正在修改c2.collection(在discard)同时迭代它(for item in c2:)。不要那样做。

    【讨论】:

    • 当然...那么将 getitem 添加到容器类并使用切片是实现此目的的最干净的方法吗?
    • @PhilipDG:我个人只想写for item in tuple(c2):。但是,如果您通常对列表执行此操作的方式是编写for item in c[:],那么可以,实现__getitem__ 来处理切片。我想这是一个你想让MyContainerClass像列表一样的问题。
    【解决方案2】:

    在迭代容器时修改容器是不安全的。

    在这种情况下,正在发生的事情是迭代只是跟踪已经过去的元素数量。所以当你取出 item1 时,迭代器知道它已经超过了容器中的第一个项目......现在是 item2。因此,它愉快地继续到item3

    【讨论】:

      猜你喜欢
      • 2014-07-30
      • 1970-01-01
      • 2013-02-01
      • 2021-08-23
      • 2014-07-20
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多