编辑:我将__iter__
添加到我的Map类中(我忘了它没有从Tree继承),但现在for循环返回“generator objects”:
<generator object _next at 0x82a4b94>
Traceback (most recent call last):
File "Map.py", line 43, in <module>
print "First: %s, Second: %s" % (pair.first(), pair.second())
AttributeError: 'generator' object has no attribute 'first'
所以我的下一个功能出现了问题,对吗?
为了好玩,我用Python创建了一个RedBlack树,它运行正常。现在从C ++复制STL我正在创建一个Map类来包装树,以替代Python dict。
问题是当我尝试循环浏览地图时,它无法正常工作。
phonebook = Map()
phonebook["Joe"] = "555-555-3422"
phonebook["Rob"] = "231-523-2357"
for pair in phonebook:
print "First: %s, Second: %s" % (pair.first(), pair.second())
我得到的错误是:
Traceback (most recent call last):
File "Map.py", line 38, in <module>
for pair in phonebook:
File "Map.py", line 19, in __getitem__
return self._tree.find(key)
File "Python/Tree/SearchTree.py", line 82, in find
raise TreeException('No node with key %s' % key)
Tree.TreeException: 'No node with key 0'
我不知道为什么它正在寻找键0,当我的键是字符串时。
使用pdb我注意到在for循环开始后,执行的第一行是调用__getitem__
,键为0 ....
地图定义为:
class Map:
def __init__(self):
self._tree = RedBlackTree()
def __getitem__(self, key):
return self._tree.find(key)
def __setitem__(self, key, item):
self._tree.insert(Pair(key, item))
根据我的理解,我必须为我的树创建一个迭代器,以使其正常工作。我不太清楚如何做到这一点,所以我环顾四周并结合了几种方法: (在我的RedBlack树实现中,NULL是一个实际节点)
class TreeIterator():
def __init__(self, root, size):
self._current = root
self._size = size
self.num_visited = 0
def __iter__(self):
return self
def next(self):
return self._next(self._current)
def _next(self, curr):
self.num_visited = self.num_visited + 1
if self.num_visited == self._size:
raise StopIteration
if curr.left is not None and curr.left is not TreeNode.NULL:
for node in _next(curr.left):
yield node
yield curr
if curr.right is not None and curr.right is not TreeNode.NULL:
for node in _next(curr.right):
yield node
并在我的SearchTree超类中:
def __iter__(self):
return TreeIterator(self.root, self.size)
我做错了什么?
答案 0 :(得分:3)
您的Map类没有__iter__
方法,因此for
会调用__getitem__
。您应该从SearchTree继承Map或在Map中实现__iter__
。
答案 1 :(得分:1)
我认为为了在条件中使用map作为迭代器,Map类必须实现next和iter。我错了吗?
基本上你要在Map类中添加__iter__()
和next()方法。
答案 2 :(得分:0)
如果你想让一个对象可迭代,以便你可以用for
循环遍历它,你必须实现__iter__()
和next()
(解释here )。
当你循环遍历具有这两种方法的对象时,Python首先在对象上调用__iter__()
。此方法返回具有next()
方法的对象。然后,Python一遍又一遍地调用next()
,逐个获取对象中的项目,直到next()
引发StopIteration
错误。
有两种简单的方法可以使您的代码正常工作。第一种方法是在地图上实现__iter__()
和next()
方法,这些方法调用self._tree
上的等价物,第二种方法是让你的地图继承自树类,然后你得到迭代,没有额外的工作。
答案 3 :(得分:0)
class xxx (object) :
def __init__ (self) :
self._values = [1, 2, 3]
def __iter__ (self) :
return self._next ()
def _next (self) :
for v in self._values :
yield v
raise StopIteration
x = xxx ()
for _ in x : print _
答案 4 :(得分:0)
next()
应该是常规函数,而不是生成器。 return
来自yield
,不要{{1}}。