如何实现 "next" 使字典对象可迭代?
How to implement "next" for a dictionary object to be iterable?
我有以下字典包装器:
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
可迭代。任何意见,将不胜感激。
字典本身不是迭代器(只能迭代一次)。您通常将它们设为 iterable,一个您可以为其生成多个 iterators 的对象。
完全放弃 next
方法,每次调用时都有 __iter__
return 一个可迭代对象。这可以像 returning 迭代器一样简单 self.container
:
def __iter__(self):
return iter(self.container)
如果您必须使您的class成为一个迭代器,您将不得不以某种方式跟踪当前迭代位置并在到达StopIteration
'end'。一个简单的实现可能是在第一次调用 __iter__
时将 iter(self.container)
对象存储在 self
上:
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
。如果基础字典被更改(添加或删除了键)并且迭代顺序被破坏,它也会引发异常。
另一种方法是每次只存储整数位置和索引到 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
在这两种情况下,您的对象都是一个 迭代器,只能迭代 一次。一旦到达终点,将无法再次启动。
如果您希望能够在嵌套循环中使用类似字典的对象,或者任何其他需要对同一对象进行多次迭代的应用程序,那么您需要实现一个 __iter__
方法return 是一个新创建的迭代器对象。
Python的可迭代对象都是这样做的:
>>> [1, 2, 3].__iter__()
<listiterator object at 0x7f67146e53d0>
>>> iter([1, 2, 3]) # A simpler equivalent
<listiterator object at 0x7f67146e5390>
对象的 __iter__
方法最简单的做法是 return 基础字典上的迭代器,如下所示:
def __iter__(self):
return iter(self.container)
有关您可能需要的更多详细信息,请参阅 this Github repository。
我有以下字典包装器:
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
可迭代。任何意见,将不胜感激。
字典本身不是迭代器(只能迭代一次)。您通常将它们设为 iterable,一个您可以为其生成多个 iterators 的对象。
完全放弃 next
方法,每次调用时都有 __iter__
return 一个可迭代对象。这可以像 returning 迭代器一样简单 self.container
:
def __iter__(self):
return iter(self.container)
如果您必须使您的class成为一个迭代器,您将不得不以某种方式跟踪当前迭代位置并在到达StopIteration
'end'。一个简单的实现可能是在第一次调用 __iter__
时将 iter(self.container)
对象存储在 self
上:
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
。如果基础字典被更改(添加或删除了键)并且迭代顺序被破坏,它也会引发异常。
另一种方法是每次只存储整数位置和索引到 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
在这两种情况下,您的对象都是一个 迭代器,只能迭代 一次。一旦到达终点,将无法再次启动。
如果您希望能够在嵌套循环中使用类似字典的对象,或者任何其他需要对同一对象进行多次迭代的应用程序,那么您需要实现一个 __iter__
方法return 是一个新创建的迭代器对象。
Python的可迭代对象都是这样做的:
>>> [1, 2, 3].__iter__()
<listiterator object at 0x7f67146e53d0>
>>> iter([1, 2, 3]) # A simpler equivalent
<listiterator object at 0x7f67146e5390>
对象的 __iter__
方法最简单的做法是 return 基础字典上的迭代器,如下所示:
def __iter__(self):
return iter(self.container)
有关您可能需要的更多详细信息,请参阅 this Github repository。