迭代字典子类中的值

时间:2017-03-03 16:45:56

标签: python python-2.7

我有一个继承自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()用于词典,而不是列表的不一致。我确实需要在代码的其他部分使用字典的功能。

2 个答案:

答案 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