可迭代对象(Iterable)
任何实现了 __iter__ 方法的对象都可以称为可迭代对象。
class Fib: def __init__(self, n): self.prev = 0 self.cur = 1 self.n = n def __iter__(self): return self fib = Fib(5) import collections print('fib is Iterable? ', isinstance(fib, collections.Iterable)) print('fib is Iterator? ', isinstance(fib, collections.Iterator)) print(next(fib))
fib is Iterable? True fib is Iterator? False Traceback (most recent call last): File "D:/MyProject/Python/insight-tools-rest/test.py", line 27, in <module> print(next(fib)) TypeError: 'Fib' object is not an iterator
迭代器(Iterator)
迭代器是用于进行迭代操作的对象,它可以像列表一样使用 for 迭代获取其中的每一个元素。当然,列表、字典属于可迭代对象,但并不是迭代器。
要将列表、字典等常见的可迭代对象变成迭代器,需要使用 iter 或者 __iter__() 进行作用:
l = [1, 2, 3] d = {'a': 1, 'b': 2, 'c': 3} print(type(l)) print(type(d)) l = l.__iter__() d = iter(d) print(type(l)) print(type(d))
<class 'list'> <class 'dict'> <class 'list_iterator'> <class 'dict_keyiterator'>
迭代器与列表的区别在于,列表是一次性把所有的元素加载到内存,迭代器则是使用延迟计算的方式返回元素,只有在调用 next 方法的时候才去计算并返回该元素,也即 call by need 的方式,for 循环本质上也是不断调用迭代器的 next 方法来进行遍历。
如果要将一个可迭代对象变成迭代器的话,还需要实现一个 __next__ 方法:
class Fib: def __init__(self, n): self.prev = 0 self.cur = 1 self.n = n def __iter__(self): return self def __next__(self): if self.n > 0: value = self.cur self.cur += self.prev self.prev = value self.n -= 1 return value else: raise StopIteration() fib = Fib(5) import collections print('fib is Iterable? ', isinstance(fib, collections.Iterable)) print('fib is Iterator? ', isinstance(fib, collections.Iterator)) print([i for i in fib])
fib is Iterable? True
fib is Iterator? True
[1, 1, 2, 3, 5]
生成器(Generator)
普通函数一般使用 return 返回一个值,但在 Python 中还有一种函数,用关键字 yield 来返回值,这种函数叫生成器。函数被调用时会返回一个生成器对象,生成器本质上还是一个迭代器(特殊的迭代器,实现方式不一样),因此在迭代操作中,生成器对象的行为和迭代器非常相似。下面是使用生成器实现的斐波那契数列:
def fib(n): prev = 0 cur = 1 while n > 0: yield cur n -= 1 prev, cur = cur, cur + prev # tmp = prev # prev = cur # cur = cur + tmp print([i for i in fib(5)])
[1, 1, 2, 3, 5]
当然也可以使用 next 不断去遍历:
fib = fib(5) print(next(fib)) print(next(fib)) print(next(fib)) print(next(fib)) print(next(fib))
1
1
2
3
5
您可能感兴趣的文章: