python iter over dict-like object

Gau*_*aut 5 python dictionary iterator

 class Test(object):

     def __init__(self, store):
         assert isinstance(store, dict)
         self.store = store

     def __getitem__(self, key):
         return self.store[key]
Run Code Online (Sandbox Code Playgroud)

我试着在这堂课上喋喋不休.在本文档中 说,实现__getitem__应该足以让我的Test类.实际上,当我试图通过它时,它并没有告诉我我不能,但我有一个KeyError:

In [10]: a = Test({1:1,2:2})

In [11]: for i in a: print i
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-11-8c9c9a8afa41> in <module>()
----> 1 for i in a: print i

<ipython-input-9-17212ae08f42> in __getitem__(self, key)
      4         self.store = store
      5     def __getitem__(self, key):
----> 6         return self.store[key]
      7

KeyError: 0
Run Code Online (Sandbox Code Playgroud)
  • 你知道这个0来自哪里吗?(引擎盖下发生了什么)

我知道我可以通过添加__iter__函数来解决它:

def __iter__(self):
    return dict.__iter__(self.store)
Run Code Online (Sandbox Code Playgroud)
  • 这是解决这个问题的最佳方法吗?(我也可能继承自dict类).

Mar*_*ers 8

您错过了您找到的文档中的关键措辞:

对于序列类型,接受的键应该是整数和切片对象.[...] [I] f应该引出序列索引集之外的值(在负值的任何特殊解释之后)IndexError.

注意:for循环期望IndexError为非法索引引发一个,以允许正确检测序列的结尾.

大胆的斜体重点是我的.如果您接受而不是整数,则表示您没有序列.

Python词汇表解释更多; 看序列定义:

一个可迭代的,它通过__getitem__()特殊方法使用整数索引支持有效的元素访问,并定义一个__len__()返回序列长度的方法.[...]注意,它dict也支持__getitem__()__len__(),但是被认为是映射而不是序列,因为查找使用任意不可变键而不是整数.

所以序列接受整数索引,这正是for迭代*时提供的.当给定一个迭代的对象时,如果没有其他方法__getitem__可用,那么构造一个特殊的迭代器,从而开始0并持续增加计数器直到IndexError被引发.在纯Python中,它将是:

def getitem_iterator(obj):
    getitem = type(obj).__getitem__  # special method, so on the type
    index = 0
    try:
        while True:
            yield getitem(obj, index)
            index += 1
    except IndexError:
        # iteration complete
        return
Run Code Online (Sandbox Code Playgroud)

实际的实现是在C中,参见PySeqIter_Type定义和函数.

改为实施该__iter__方法 ; 它存在时使用.由于你包装了一个字典,你可以简单地返回该字典的迭代器(使用iter()函数而不是直接调用特殊方法):

def __iter__(self):
    return iter(self.store)
Run Code Online (Sandbox Code Playgroud)

*从技术上讲,for不提供此功能.for只是使用iter(obj)而且当没有方法可用时,它就是产生特殊迭代器的调用__iter__.