【发布时间】:2012-09-10 06:00:28
【问题描述】:
如果我有一个带有接口的类:
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
【问题讨论】:
-
你们是如何实现
next的? -
如果
foo是dict,您可以使用for k in foo.keys()[:]。在其他情况下,它取决于next方法的实现。 -
@DavidRobinson 我不是——这只是一个界面。我想知道您如何为具有任意数据结构的任意类执行此操作,因为我认为这种情况相当普遍。
标签: python iterator concurrentmodification