问题描述
我有以下字典包装器:
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
我的问题是我不知道如何实现 next
方法以使 MyDict
可迭代.任何意见,将不胜感激.
My problem is that I don't know how to implement the next
method to make MyDict
iterable. Any advice would be appreciated.
推荐答案
字典本身不是迭代器(只能迭代一次).您通常将它们设为 iterable,您可以为其生成多个 iterators 的对象.
Dictionaries are themselves not an iterator (which can only be iterated over once). You usually make them an iterable, an object for which you can produce multiple iterators instead.
完全删除 next
方法,并让 __iter__
在每次调用时返回一个可迭代对象.这可以像返回 self.container
的迭代器一样简单:
Drop the next
method altogether, and have __iter__
return an iterable object each time it is called. That can be as simple as just returning an iterator for self.container
:
def __iter__(self):
return iter(self.container)
如果你必须让你的类成为一个迭代器,你必须以某种方式跟踪当前的迭代位置并在到达结束"时提高 StopIteration
.一个简单的实现可能是在第一次调用 __iter__
时将 iter(self.container)
对象存储在 self
上:
If you must make your class an iterator, you'll have to somehow track a current iteration position and raise StopIteration
once you reach the 'end'. A naive implementation could be to store the iter(self.container)
object on self
the first time __iter__
is called:
def __iter__(self):
return self
def next(self):
if not hasattr(self, '_iter'):
self._iter = iter(self.container)
return next(self._iter)
此时 iter(self.container)
对象会为您跟踪迭代位置,并在到达结束时引发 StopIteration
.如果底层字典被更改(添加或删除键)并且迭代顺序被破坏,它也会引发异常.
at which point the iter(self.container)
object takes care of tracking iteration position for you, and will raise StopIteration
when the end is reached. It'll also raise an exception if the underlying dictionary was altered (had keys added or deleted) and iteration order has been broken.
另一种方法是每次只存储整数位置并索引到 list(self.container)
中,而忽略插入或删除可以改变迭代顺序的事实字典:
Another way to do this would be to just store in integer position and index into list(self.container)
each time, and simply ignore the fact that insertion or deletion can alter the iteration order of a dictionary:
_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
在这两种情况下,您的对象都是一个迭代器,只能迭代一次.一旦到达终点,就不能再重新开始了.
In both cases your object is then an iterator that can only be iterated over once. Once you reach the end, you can't restart it again.
这篇关于如何实现“下一步"?字典对象是可迭代的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!