简简单单讲清楚Python迭代器与生成器
2018-11-23 本文已影响0人
zlrs
迭代
循环中执行一遍循环体且选择下一个进入循环体的变量的过程
迭代器
迭代器是定义__next__
方法的对象。(并用StopIteration标识迭代的完成)
区分可迭代对象和迭代器
可迭代对象是含有__iter__()
方法的对象。__iter__()
方法返回一个迭代器。String, tuple, list,dict都是可迭代对象,因为它们都实现了__iter__()
方法;但是他们都不是迭代器,因为它们都没有实现__next__()
方法。
>>> print('__iter__' in dir(list), '__iter__' in dir(tuple), '__iter__' in dir(dict), '__iter__' in dir(str))
True True True True
>>> print('__next__' in dir(list), '__next__' in dir(tuple), '__next__' in dir(dict), '__next__' in dir(str))
False False False False
for循环遍历可迭代对象的过程
for循环遍历可迭代对象时,首先调用iter方法,得到一个迭代器;之后反复对迭代器调用其next方法,直到捕捉到StopIteration异常。
>>> for _ in 'abc':
print(_)
a
b
c
String, tuple, list不是迭代器,因为它们没有实现__next__
方法。
>>> next('abc')
TypeError: 'str' object is not an iterator
>>> next([1])
TypeError: 'list' object is not an iterator
>>> next((1,2))
TypeError: 'tuple' object is not an iterator
用iter()函数,以String, tuple, list作为参数,可以创建一个迭代器。
>>> iter_s = iter('abc')
>>> next(iter_s)
'a'
自定义迭代器
下面这个类既是迭代器,又是可迭代对象。因为它同时实现了iter和next两个方法.
# 迭代类
class Fibs():
def __init__(self,max):
self.a = 0
self.b = 1
self.max = max
self.count_next = 0
def __iter__(self):
print("__iter__() is called")
return self
def __next__(self):
self.count_next += 1
print("__next__() is called {}".format(self.count_next))
fib = self.a
self.a,self.b = self.b,self.a + self.b
if fib > self.max:
print("raise StopIteration")
raise StopIteration
return fib
生成器
生成器是一种在运行时生成值的迭代器。生成器只能完整遍历一次。
- 用Generator expressions表示一个生成器
Generator expressions是在List comprehensions语法中用圆括号代替方括号
可以认为圆括号中的for语句隐式定义了一个生成器函数
>>> g = (x**2 for x in range(4))
>>> type(g)
<class 'generator'>
- 调用生成器函数将返回一个生成器
生成器函数是使用yield语句的函数。
和普通函数不同,生成器函数在调用时返回一个生成器。并且函数的真正运行,不是在函数调用时,而是在调用其返回的生成器时。
生成器函数为生成器提供生成下一个迭代值的规则。每当生成器迭代一次,函数会运行至下一个yield语句,然后暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
使用生成器的好处是可以为程序节约大量的内存。(比较一下:当需要迭代10000次时,一个含有10000个元素的列表占的内存要比生成器要大得多;因为生成器只是一段代码而已,其元素是每次迭代时动态生成的)
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
判断一个对象是否可迭代
from collections import Iterable
isinstance(<要判断的对象>, Iterable)
isinstance('abc', Iterable) #str是否可迭代
isinstance((x**2 for x in range(5)), Iterable) #generator是否可迭代
isinstance(123, Iterable) #整数是否可迭代
参考
http://www.runoob.com/python3/python3-iterator-generator.html
http://greenteapress.com/thinkpython2/html/thinkpython2020.html