iter() 返回了“dict_items”类型的非迭代器

r.o*_*ook 5 python class python-3.x

这让我发疯。下面是一个class我正在搞乱的,目标是有一种支持动态属性分配的方法。 请暂时忘记糟糕的实现或为什么我不只使用字典,我知道还有其他方法可以做到这一点(例如Enum)但这是我之前的测试代码,现在它成为我寻找原因的追求不工作。

class Family(object):
    def children(self):
        return self.__dict__.values()

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __getitem__(self, item):
        return self.__dict__[item]

    def __repr__(self):
        return str(self.__dict__)

    def __iter__(self):
        return self.__dict__.items()
Run Code Online (Sandbox Code Playgroud)

这一切看起来都很好,我启动了一个测试对象,如下所示:

foo = Family()
foo.a = 'foo'
foo.b = 'bar'

[i for i in foo]
Run Code Online (Sandbox Code Playgroud)

现在预期的结果是[('a', 'foo'), ('b', 'bar')],但我得到的是:

TypeError: iter() returned non-iterator of type 'dict_items'

我想我可能把__iter__方法搞砸了,所以我检查如下:

type(foo.__iter__())
# <class 'dict_items'>
type(foo.__dict__.items())
# <class 'dict_items'>

[i for i in foo.__dict.__items()]
# [('a', 'foo'), ('b', 'bar')]

foo.__dict__.items() == foo.__iter__()
# True
Run Code Online (Sandbox Code Playgroud)

如果它们都相同,为什么不起作用[i for i in foo]

sha*_*awn 12

那这个呢:

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

Python 想要一个iterator, 而不是一个list(或其他类似列表/类似字典的对象)

请记住: a listordict不是 an iterator, aniterator通常(为了便于理解)是指向listor项的指针(游标)dict

  • FWIW,在 Python 3 中,`dict.items()` 返回一个 [视图对象](https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects),而不是一个列表。 (2认同)
  • @Idlehands 正确。`for` 在你给它的可迭代对象上调用 `iter`。 (2认同)