2017-03-03 81 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