Mey*_*sam 1 python dictionary iterator iterable python-2.7
我有一个字典的以下包装器:
class MyDict:
def __init__(self):
self.container = {}
def __setitem__(self, key, value):
self.container[key] = value
def __getitem__(self, key):
return self.container[key]
def __iter__(self):
return self
def next(self):
pass
dic = MyDict()
dic['a'] = 1
dic['b'] = 2
for key in dic:
print key
Run Code Online (Sandbox Code Playgroud)
我的问题是我不知道如何实现next方法来进行MyDict迭代.任何意见,将不胜感激.
Mar*_*ers 11
字典本身不是迭代器(只能迭代一次).您通常将它们设置为可迭代的对象,您可以为其生成多个迭代器.
next完全删除该方法,并在__iter__每次调用时返回一个可迭代对象.这可以像返回迭代器一样简单self.container:
def __iter__(self):
return iter(self.container)
Run Code Online (Sandbox Code Playgroud)
如果必须使您的类成为迭代器,则必须以某种方式跟踪当前迭代位置并StopIteration在达到"结束"时加速.一个天真的实现可能是第一次存储iter(self.container)对象被调用:self__iter__
def __iter__(self):
return self
def next(self):
if not hasattr(self, '_iter'):
self._iter = iter(self.container)
return next(self._iter)
Run Code Online (Sandbox Code Playgroud)
此时,iter(self.container)对象负责跟踪您的迭代位置,并StopIteration在到达结束时进行提升.如果底层字典被更改(添加或删除了键)并且迭代顺序已被破坏,它也会引发异常.
另一种方法是在list(self.container)每次存储整数位置和索引时,只需忽略插入或删除可以改变字典迭代顺序的事实:
_iter_index = 0
def __iter__(self):
return self
def next(self):
idx = self._iter_index
if idx is None or idx >= len(self.container):
# once we reach the end, all iteration is done, end of.
self._iter_index = None
raise StopIteration()
value = list(self.container)[idx]
self._iter_index = idx + 1
return value
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,您的对象都是迭代器,只能迭代一次.到达最后,您无法再次重新启动它.
例如,如果您希望能够在嵌套循环中使用类似字典的对象,或者任何其他需要对同一对象进行多次迭代的应用程序,那么您需要实现一个__iter__返回新创建的迭代器对象的方法。
Python 的可迭代对象都是这样做的:
>>> [1, 2, 3].__iter__()
<listiterator object at 0x7f67146e53d0>
>>> iter([1, 2, 3]) # A simpler equivalent
<listiterator object at 0x7f67146e5390>
Run Code Online (Sandbox Code Playgroud)
对于对象的__iter__方法来说,最简单的事情就是返回底层字典上的迭代器,如下所示:
def __iter__(self):
return iter(self.container)
Run Code Online (Sandbox Code Playgroud)
有关比您可能需要的更多详细信息,请参阅此 Github 存储库。