如果我想实现这个,我该怎么做?
我知道每当我们拨打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
答案 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)