生成器
- 列表生成式能够生成列表,但是如果需要的列表较大,占用的内存空间就会很大,这时就会需要生成器。生成器保存了生成每个元素的计算方式,需要用时再生成某个元素,从而节省了大量的内存空间。
- 生成器的第一种创建方式:将列表生成式最外面的中括号改为圆括号。
- 通过
next(generator_object_name)
就能够每次让生成器生成一个值。下面举例说明:
>>> a = (x for x in range(10))
>>> a
<generator object <genexpr> at 0x000000886B3898E0>
>>> next(a)
0
>>> next(a)
1
>>> next(a)
2
>>> next(a)
3
- 生成器的第二种创建方式:包含
yield
关键字的函数就是生成器,此时调用函数名已经不再是执行函数中的代码而是创建一个生成器对象。通过调用next(generator_object_name)
来执行函数中的代码从而每次生成一个值。
yield
关键字的作用是让函数暂停执行并返回一个值,下一次调用next()
方法时就从上次yield
暂停的地方继续执行,直到下一次执行yield
。下面举例对第二种进行说明:
def fibonacci():
a, b = 0, 1
for i in range(10):
print("----1----")
yield b
print("----2----")
a, b = b, a+b
print("----3----")
generator = fibonacci()
for x in range(3):
v = next(generator)
print(v)
- 运行上面代码输出内容如下。从输出结果也能够看出每次执行至
yield
关键字都会暂停,下次会从上次暂停的地方继续执行。
--------
--------
--------
--------
--------
--------
--------
- 生成器还可以用
for
循环进行迭代,且for
循环会自动停止(不像使用next()
在最后不能继续生成时会报错):
def fibonacci():
a, b = 0, 1
for i in range(10):
print("----1----")
yield b
print("----2----")
a, b = b, a+b
print("----3----")
generator = fibonacci()
for x in generator:
print(x)
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
- 生成器对象除了
__next__()
方法之外还有一个send()
方法也能实现让生成器继续向下走一步的功能,它们的区别在于send()
方法可以传入一个参数用来当做yield variable
语句的返回值。下面用代码来进行解释:
def test():
for i in range(5):
print("----1----")
temp = yield i
print("----2----")
print(temp)
print("----3----")
t = test()
a = t.__next__()
print(a)
b = t.send("hello")
print(b)
- 以上代码的执行结果如下。从输出结果可以看出
send()
语句执行是从第四行代码的赋值语句开始的,首先将传入的参数赋值给temp
变量,然后再继续执行至下一次yield
语句。
--------
--------
--------
--------
迭代器
- 可以用
for
循环取值的对象就称为可迭代对象,比如列表、字符串、元组、字典和集合等,还有一类就是生成器。
- 判断一个对象是否是可迭代对象可以使用如下语句:
from collections import Iterable
b = isinstance("abc",Iterable)
print(b)
b = isinstance({},Iterable)
print(b)
b = isinstance([],Iterable)
print(b)
b = isinstance((x for x in range(10)),Iterable)
print(b)
b = isinstance(100,Iterable)
print(b)
True
True
True
True
False
- 可以被
next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
- 判断一个对象是否是迭代器可以使用如下语句:
from collections import Iterator
b = isinstance("abc",Iterator)
print(b)
b = isinstance({},Iterator)
print(b)
b = isinstance([],Iterator)
print(b)
b = isinstance((x for x in range(10)),Iterator)
print(b)
- 运行输出结果如下。从结果可以看出可迭代对象不一定是迭代器,迭代器一定是可迭代对象,且生成器就是迭代器。
False
False
False
True
- 可以使用
iter()
将可迭代对象转变为迭代器。
- 一个类定义了
_iter_
方法和_next_
方法,那么它所生成的对象就是迭代器。