afaik,完整且正确的答案。
for,在 for 循环和列表推导中,在 X 上调用 iter()。如果X 具有__iter__ 方法或__getitem__ 方法,iter() 将返回一个可迭代对象。如果两者都实现,则使用__iter__。如果两者都没有,你会得到TypeError: 'Nothing' object is not iterable。
这实现了__getitem__:
class GetItem(object):
def __init__(self, data):
self.data = data
def __getitem__(self, x):
return self.data[x]
用法:
>>> data = range(10)
>>> print [x*x for x in GetItem(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
这是一个实现__iter__的例子:
class TheIterator(object):
def __init__(self, data):
self.data = data
self.index = -1
# Note: In Python 3 this is called __next__
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
def __iter__(self):
return self
class Iter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return TheIterator(data)
用法:
>>> data = range(10)
>>> print [x*x for x in Iter(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
如您所见,您需要实现迭代器和返回迭代器的__iter__。
您可以将它们组合起来:
class CombinedIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
self.index = -1
return self
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
用法:
>>> well, you get it, it's all the same...
但是你一次只能有一个迭代器。
好的,在这种情况下,您可以这样做:
class CheatIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return iter(self.data)
但这是作弊,因为您只是在重复使用 list 的 __iter__ 方法。
更简单的方法是使用yield,并将__iter__ 变成一个生成器:
class Generator(object):
def __init__(self, data):
self.data = data
def __iter__(self):
for x in self.data:
yield x
最后一种是我推荐的方式。简单高效。