我有一个继承自OrderedDict的类。我希望能够迭代它的值,而不是它的键。
我相信以下代码应该有效,但事实并非如此。它不是打印值“one”和“two”,而是给出某种递归错误(显示在代码下面)。
from collections import OrderedDict
class A(OrderedDict):
def __init__(self):
super(A, self).__init__()
def __iter__(self):
for value in self.values():
yield value
return
a = A()
a[1] = "one"
a[2] = "two"
for thing in a:
print str(thing)
我得到的错误如下:
File "T:\***\Test024.py", line 8, in __iter__
for value in self.values():
File "C:\Python27\Lib\collections.py", line 111, in values
return [self[key] for key in self]
RuntimeError: maximum recursion depth exceeded while calling a Python object
为什么上面的例子不起作用?我知道我可以使用类似for thing in a.values():
的循环迭代值,但我想避免使用.values()
用于词典,而不是列表的不一致。我确实需要在代码的其他部分使用字典的功能。
答案 0 :(得分:1)
正如您在异常回溯中所看到的,OrderedDict.values
遍历dict:
File "/usr/lib64/python2.7/collections.py", line 123, in values
return [self[key] for key in self]
由于您已覆盖__iter__
函数,因此会导致无限递归。
要解决此问题,您必须覆盖values
函数,例如:
def values(self):
return [self[key] for key in OrderedDict.__iter__(self)]
答案 1 :(得分:0)
这是一个非常糟糕的解决方案,但通过修改原始OrderedDict
的实现(/usr/local/lib/python2.7/collections.py:90
),您可以执行以下操作:
from collections import OrderedDict
class A(OrderedDict):
def __init__(self):
super(A, self).__init__()
def __iter__(self):
'od.__iter__() <==> iter(od)'
# Traverse the linked list in order.
root = self._OrderedDict__root
curr = root[1]
while curr is not root:
yield self[curr[2]]
curr = curr[1]
a = A()
a[1] = "one"
a[2] = "two"
for thing in a:
print str(thing)
运行时:
$ ./foo.py
one
two