您的位置:首页 > 编程语言 > Python开发

Python学习笔记(10)-生成器generator和迭代器Iterator

2017-01-15 01:22 1026 查看

生成器generator

在创建列表的时候,存储的内容和大小已经固定,若创建的列表包含大量的元素,则会占据很大的存储空间,而且若只需要访问列表的前几个元素,则会造成较大的资源浪费。而使用生成器
generator
即可避免这样的问题,
generator
是根据已经写好的逻辑,动态循环创建的。

1.第一种创建方法,把列表解析的符号
[]
换成
()
,如下

代码:

a = [n for n in range(5)]  # 返回的是list,可直接输出存储的数据
b = (n for n in range(5))  # 返回的是个generator,不能直接输出数据
print(a)
print(b)


结果:

[0, 1, 2, 3, 4]
<generator object <genexpr> at 0x0000000001131360>


1.1 获取generator存储的数据,可以用
next()
方法,例如

代码:

b = (n for n in range(5))
print(next(b))  # 输出3次
print(next(b))
print(next(b))


结果:

0
1
2


(注意:若
next()
输出的次数大于生成器存储的元素个数,则会抛出
StopIteration
错误)

1.2 查看generator存储的数据,每次都调用
next()
太过于繁琐,建议用
for...in...
循环,例如

代码:

b = (n for n in range(5))
for value in b:
print(value)


结果:

0
1
23
4


for
循环调用,可以不用担心抛出
StopIteration
错误

2.第二种创建方法,在函数定义中使用
yield
关键字,则该函数即为生成器函数,如下

代码:

def Fibonacci(number):
n, a, b = 0, 0, 1
while n < number:
yield b   # 使用yield关键字,将b存储到generator中
a, b = b, a + b  # a = b , b = a + b
n += 1
return 'over'  # 在生成器函数中的return,不返回信息,而是将值存储在抛出的StopIteration中,可通过捕获异常来获取

print([n for n in Fibonacci(8)])  # 使用列表解析,将结果存储到数组中,为了看着好看而已→_→


结果:

[1, 1, 2, 3, 5, 8, 13, 21]


普通函数和生成器函数的区别:

普通函数中遇到
return
语句或者执行到函数末尾会自动返回,而在生成器函数中,
return
是不返回的,而是在调用
next()
函数之后开始执行,而在
yield
处返回,下次在调用
next()
则再上次停止的
yield
处继续开始执行

2.1 通过
try-except
语句来获取
return
的返回值,如下

代码:

result = Fibonacci(8)
while True:
try:
x = next(result)  #  其实for循环就是一次次的执行next()函数
except StopIteration as e:
print('返回值是:', e.value)
break


结果:

返回值是: over


e.g.

利用生成器函数,将杨辉三角的每一行数据存储到list中输出。

代码:

def YHtriangle(max):  # 构造杨辉三角的逻辑  max>2时,每个数都等于上一行同一位置的数+这个位置前一位置的数
n, L = 0, [1]
while n < max:
yield L  # 此处将L列表存储到生成器中
L.append(0) # 存储后,在列表末尾添加0,为了下一行计算数据
L = [L[i - 1] + L[i] for i in range(len(L))]  # 注意是range(len(L)),i-1=-1,每次取值都是上一句添加的0,
n += 1

def getYHtriangle(num):  # 输出数据
for n in YHtriangle(num):
print(n)

getYHtriangle(4)  # 调用函数


结果:

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]


迭代器Iterator和可迭代对象Iterable

笔记(3)中记过,可使用
collections
模块的
Iterable
类型来判断是否可被
for
循环,补充,生成器generator或者是生成器函数也是可迭代对象
Iterable


可以被
next()
函数调用,并且不断返回下一个值的对象,叫做迭代器
Iterator


同样可以使用
isinstance()
函数来判断是否是迭代器(需要先导入
Iterable
)

代码:

from collections import Iterator

print(isinstance(123, Iterator))    # 不是可迭代对象Iterable,也不是迭代器Iterator
print(isinstance('abc', Iterator))  # 字符串,列表,字典虽然可迭代Iterable,但不是迭代器Iterator
print(isinstance(['a', 'b'], Iterator))
print(isinstance(('a', 3), Iterator))
print(isinstance((n for n in range(5)), Iterator))  # 只有生成器是一个迭代器


结果:

False
False
False
False
True


字符串,列表,字典虽然只是可迭代,不是迭代器,但是可以通过函数
iter()
获取一个迭代器
Iterator
,例如。

代码:

from collections import Iterator

L = [1, 2, 3, 4]
print(isinstance(L, Iterator))
print(isinstance(iter(L), Iterator))


结果:

False
True
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: