生成器 (generator)的定义:在Python 中可以一边循环一边计算的机制。
第一种使用方式:将存在一定规律(很重要)的列表 生成 生成器。
作用:就我目前的了解来看,生成器可以用于节省内存,如:生成一个从1到100000 的列表和使用 生成器生成的对象 两者的区别在于 列表的内存远远大于 生成器,原因在于: 列表是1到100000 的每个数都需要占用内存, 生成器相当于占用一个函数的内存(个人理解,可能存在偏差)。
下面举例看看两者区别:
import sys
a = [x for x in range(1000)]
print sys.getsizeof(a) #此处输出的内存大小为 9032
#生成器的使用方式,将[] 转换为()
b = (x for x in xrange(1000)]
print sys.getsizeof(b) #此处 输出的内存大小为 80
#如何使用生成器方式1-- 使用next()
print next(b) #将顺序输出 b 中的元素,直到无数据后,报错 StopIteration, 使用该方式调用时 需要捕获该异常
#如何使用生成器方式2-- 使用for 循环 (推荐),不需要关心StopIteration的错误
for num in b:
print num
第二种使用方式:如果某个函数中带有 yield 关键字 ,那么该函数就不再是一个普通的函数,而是一个 生成器函数。
作用:当某些推算的算法比较复杂,需要借助函数实现时,可以使用生成器。
范例: (使用著名的斐波拉契数列(除第一个和第二个数之外,其余数由前两个数相加得到)进行演示)
#正常函数
def Fib(max):
n,a,b = 0,0,1
while n < max:
print b
a,b = b,a+b
n += 1
return 'succ'
#使用生成器
def Fib1(max):
n,a,b = 0,0,1
while n < max:
#print b
yield b
a,b = b,a+b
n += 1
#return 'succ' #python 3.0 支持 yield 之后return , 2.0 不支持,若增加 return会抛SyntaxError: 'return' with argument inside generator异常
if __name__ == '__main__':
Fib(10)
datas = Fib1(10)
#用法1,使用 __next__() 函数
print datas
print datas.__next__()
#用法2,使用for 循环(推荐)
for data in datas:
print data
迭代器
可迭代对象(Iterable):可以直接作用于for循环的对象,如list、tuple、dict、set、str、生成器(generator)和生成器函数(generator function)。
迭代器(Iterable):可以被next()函数调用并不断返回下一个值的对象称为迭代器。
可迭代对象和迭代器 两者的区别: 可迭代对象可是一个数据流,无法知道它的长度,可通过next() 进行持续调用,直到抛出StopIteration 错误。 因此 可迭代对象甚至可以展示一个无限制的数据流,这是迭代器无法做到的。
迭代器转换为 可迭代对象 :使用 iter()函数,
from collections import Iterable
a = [1,2,3,4]
print isinstance(a,list) #True
print isinstance(a,Iterator) #False
b = iter(a)
print isinstance(b,list) #False
print isinstance(b,Iterator) #True
for num in b:
print num