如果我有一个带有接口的类:
class AnIteratable(object):
  def __init__(self):
    #initialize data structure
  def add(self, obj):
    # add object to data structure
  def __iter__(self):
    #return the iterator
  def next(self):
    # return next object
...我将如何设置,以便如果add()被称为中间迭代,则会抛出异常,类似于:
In [14]: foo = {'a': 1}
In [15]: for k in foo:
   ....:     foo[k + k] = 'ohnoes'
   ....:     
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-15-2e1d338a456b> in <module>()
----> 1 for k in foo:
      2     foo[k + k] = 'ohnoes'
      3 
RuntimeError: dictionary changed size during iteration
更新:
如果接口需要更多方法,请随意添加。我还删除了__iter__().
更新 #2 根据 kindall 的回答,我模拟了以下伪实现。请注意,_datastruture 和索引到它的相关方法是抽象的,类编写者必须编写他/她自己的数据结构遍历和位置指针机制。
class AnIteratable(object):
  def __init__(self):
    self._itercount = 0
    self._datastructure = init_data_structure() #@UndefinedVariable
    # _datastructure, and the methods called on it, are abstractions.
  def add(self, obj):
    if self._itercount:
      raise RuntimeError('Attempt to change object while iterating')
    # add object to data structure
  def __iter__(self):
    self._itercount += 1
    return self.AnIterator(self)
  class AnIterator(object):
    def __init__(self, aniterable):
      self._iterable = aniterable
      self._currentIndex = -1 #abstraction
      self._notExhausted = True
    def next(self):
      if self._iterable._datastructure.hasNext(self._currentIndex):
        self._currentIndex += 1
        return self._iterable._datastructure.next(self._currentIndex)
      else:
        if self._notExhausted:
          self._iterable._itercount -= 1
        self._notExhausted = False
        raise StopIteration
    def __next__(self):
      return self.next()
    # will be called when there are no more references to this object
    def __del__(self): 
      if self._notExhausted:
        self._iterable._itercount -= 1
更新 3
在阅读了更多内容后,似乎__del__可能不是正确的方法。以下可能是更好的解决方案,尽管它需要用户显式释放未用尽的迭代器。
    def next(self):
      if self._notExhausted and 
              self._iterable._datastructure.hasNext(self._currentIndex):
      #same as above from here
    def discard(self):
      if self._notExhausted:
        self._ostore._itercount -= 1
      self._notExhausted = False