除非在iPython控制台中手动输入内容,否则函数不会成功循环遍历类实例

时间:2014-11-04 02:08:46

标签: python class object

这使用类似于this question I asked的注册表。在一个类中,我有一个该类的所有实例的注册表(这次是一个列表的形式)。使用某些坐标初始化实例,但这些将在用户使用程序时更改。我已经创建了一个重置​​这些坐标的函数(简化版)

class Foobar:
    _registry = []
    def __init__(self, position=[0,0,0], direction=[0,0,1]):
        self._pos = position # can change later
        self._pos0 = position # stored static copy of initial position
        self._dir = direction
        self._dir0 = direction # stored initial direction
        self._registry.append(self) # adds instance to registry
        ...
    def remove(self):
        Foobar._registry.remove(self) # removes instance from registry
    def reset(self):
        self.remove()
        Foobar.__init__(self, self._pos0, self._dir0)
        # re-initialises instance with starting parameters
    ...
def reset_all():
    # note: outside of Foobar
    for item in Foobar._registry:
        item.reset()

现在,如果我这样做,这是有效的

>>> A = Foobar([0,0,0], [0,0,1])
>>> A.do_something_that_adds_more_pos_&_dir_vectors()
>>> B = Foobar(... # same sort of thing. C, D etc
>>> A.reset()
>>> B.reset()
>>> C.reset()
>>> D.reset()

那些都重置好了。如果我进入IPython控制台

>>> for item in Foobar._registry:
...     item.reset()

所有对象都重置正常。但是,如果我改为reset_all(),我发现有些实例会重置,而其他实例则不会重置。如果我继续做reset_all()最终他们都会重置,但不是一次性。发生了什么事?!

额外信息:我将位置和方向向量附加到这些对象。然后我绘制了矢量所指示的路径。如果我尝试reset_all()然后再次尝试绘制它们,其中一些会被重置并且不再显示在图上(如预期的那样),但大约有一半仍会出现。

1 个答案:

答案 0 :(得分:2)

当你迭代它时,你间接地突变Foobar._registry。这是非法的,理论上可以导致从正常工作到重新格式化硬盘的任何事情,但实际上它通常意味着你最终会跳过某些值。

最简单的改变是迭代副本:for item in Foobar._registry[:]: