迭代器协议。这是黑魔法吗?

时间:2017-03-02 04:38:01

标签: python python-2.7 iterator

所以我一直在编写迭代器,我认为我理解它们。但是我今晚一直在努力解决一些问题,而且我玩的越多,我就越困惑。

我认为对于迭代器,您必须实现next__next__(或__iter__)。当你第一次尝试迭代迭代器时,将调用next方法,然后调用StopIteration直到class Iter(object): def __iter__(self): return iter([2, 4, 6]) def next(self): for y in [1, 2, 3]: return y iterable = Iter() for x in iterable: print(x) 被引发。

当我运行此代码时

2 4 6

输出为__iter__。因此,next被调用,但不是next。这似乎与我找到的here文档相符。但那时我脑海里浮现出更多问题。

具体来说,如果它不是next的实现,那么容器类型和迭代器之间的区别是什么?我如何知道我的课程将以哪种方式对待?最重要的是,如果我想编写一个使用for x in Iter()时调用UITextBorderStyleNone方法的类,我该怎么做?

2 个答案:

答案 0 :(得分:6)

列表是 iterable ,但它不是迭代器。比较和对比:

>>> type([])
list
>>> type(iter([]))
list_iterator

在列表上调用iter会创建并返回一个新的迭代器对象,用于迭代该列表的内容。

在你的对象中,你只返回一个列表迭代器,特别是列表[2, 4, 6]上的迭代器,这样对象就不知道产生元素1,2,3。

def __iter__(self):
    return iter([2, 4, 6])  # <-- you're returning the list iterator, not your own

这是一个更基本的实现,符合Python 2中的迭代器协议,它不会因依赖列表迭代器,生成器或任何花哨的东西而混淆。

class Iter(object):

    def __iter__(self):
        self.val = 0
        return self

    def next(self):
        self.val += 1
        if self.val > 3:
            raise StopIteration
        return self.val

答案 1 :(得分:2)

根据您链接的文档,迭代器的__iter__方法应该返回自身。所以你的迭代器根本就不是迭代器:当for调用__iter__来获取迭代器时,你给它iter([2,4,6]),但你应该给它self

(另外,我不认为您的next方法符合您的意图:每次调用它都会返回1,并且永远不会引发StopIteration。因此,如果你修复了__iter__,那么你的迭代器将是一个无限流的迭代器,而不是有限列表[1, 2, 3]。但这是一个副问题。)