2017-03-03 64 views
-1

我有一个继承自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

[意见反馈]删除'return' – sangheestyle

+0

这样做的意义何在?人们会期望字典在迭代中返回键而不是值。只需使用'a.itervalues()'。 –

+2

@sangheestyle这不会做任何事情。 –

回答

1

正如你可以在异常回溯看,OrderedDict.values迭代的字典:

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)] 
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