__iter__和__next__的特殊用途

时间:2014-11-25 23:55:13

标签: python class iterator

如果我想实现这个,我该怎么做?

我知道每当我们拨打for i in object:

首先转到def __iter__(self)然后转到def __next__(self),但我看不到iter转移 对下一个的任何争论。那怎么样?

class MyClass(object):
    def __init__(self):
        self.data = {"a":1, "b":2, "c":3, "special":0}


for i in MyClass(): # for i in self.data, if i != "special" yield i
    print(i)

预期产出:

a
b
c

4 个答案:

答案 0 :(得分:4)

使用__iter____next__特殊方法创建迭代器类的关键在于它是,这意味着它可以显式存储状态,在实例属性中。

例如:

class MyClass(object):
    def __init__(self, *filtered_keys):
        self.data = {"a":1, "b":2, "c":3, "special":0}
        self.filtered_keys = set(filtered_keys)
        self.iterator = iter(self.data)
    def __iter__(self):
        return self
    def __next__(self):
        while True:
            key = next(self.iterator)
            if key not in filtered_keys:
                return key

for i in MyClass("special"):
    print(i)

如果您不想创建迭代器,而只想创建一个可迭代,那就是__iter__方法没有'返回self,而是返回带有__next__的其他对象(并在__iter__内返回自身),您可以在__iter__中返回任何内容。

def __iter__(self):
    return (key for key in self.data if key != 'special')

或者您甚至可以使__iter__本身成为生成器函数,在这种情况下它会返回一个生成器:

def __iter__(self):
    for key in self.data:
        if key != 'special':
            yield key

或者,如果您愿意:

def __iter__(self):
    yield from (key for key in self if key != 'special')

这样,状态现在位于__iter__方法和/或它返回的内容中。

答案 1 :(得分:3)

您可以将__iter__特殊方法过滤掉"special" generator expression

>>> class MyClass(object):
...     def __init__(self):
...         self.data = {"a":1, "b":2, "c":3, "special":0}
...     def __iter__(self):
...         return (x for x in self.data if x != "special")
...
>>> for i in MyClass():
...     print(i)
...
a
c
b
>>>

答案 2 :(得分:3)

自定义迭代的另一个例子:

#!/usr/bin/env python

class Custom(object):
    def __init__(self):
        self.data = {"a":1, "b":2, "c":3, "special":0}
        self.current = 0

    def __iter__(self):
        return self

    def next(self):
        key = [k for k, v in self.data.iteritems() if v == self.current]
        if not key:
            raise StopIteration
        self.current += 1
        return key[0]

if __name__ == '__main__':
    obj = Custom()
    for i in obj:
        print(i)

打印按值排序的数据中的键:

'special'
'a'
'b'
'c'

要点:https://gist.github.com/miku/01d50434b232367f8bfd#file-ex-py

答案 3 :(得分:0)

我不喜欢自己的实施。 我想做一些东西只是迭代dict键一次。 但是这个方法将所有键都取出,转换为set,并丢弃set上的特殊键和iter。 这太复杂了。还有更好的主意吗?

def __iter__(self):
    a = set(self.data.keys())
    a.discard("special")
    return iter(a)