学习笔记-python生成器、迭代器、可迭代
一、生成器
在Python中,一边循环一边计算的机制,称为生成器:generator
列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。
如:仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
如果列表元素按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
简单一句话:我又想要得到庞大的数据,又想让它占用空间少,那就用生成器!
生成器概念
生成器的创建可以通过关键字yield
获取生成器的元素可以通过:next(生成器) 、生成器.next()、生成器.send(传参)
1、创建一个生成器
创建生成器的方式有两种:
- 一种是通过推导式的方式创建生成器;
- 一种是通过函数中添加关键字yield的方式创建生成器
使用函数中添加yield关键字创建生成器需要注意:
- 需要先定义函数,在函数中需要使用关键子yield,调用函数得到一个生成你对象,再结合next
- 只要遇到yield则回i爱你搞起后面值返回并暂停,下次执行时,从该位置开始
- 一个函数中可以有多个yield
- 如果函数有返回值,返回值的内容会作为生成器元素取完后报错的内容:StopIteration:生成器函数返回值
g = (x for x in range(1,3)) # 通过推导式生成一个生成器
print(type(g))
print(next(g))
t = next(g)
print(next(g, 0)) # 配置默认值为0,当next最后一个值时将会报错,设置默认值将不会报错
from collections import Iterable, Iterator
import types
print(isinstance(t, Iterable)) # 判断是否为可迭代的
print(isinstance(t, Iterator)) # 判断是否为迭代器
print(isinstance(g, types.GeneratorType)) # 判断是否为生成器
def func(): # 通过函数中yield关键字的方式创建
for i in range(1, 3):
yield i # 类似于return和暂停,下次next时从这个位置开始
print('i:{}'.format(i))
yield "ok" # 一个函数中可以有多个yield
f = func()
print(next(f))
print(f.__next__()) # 同next(f)
print(next(f))
2、为生成器中传参
为生成器中传参可以使用send()方法来进行,在传参时需要注意:
第一个值需要先传None,否则会报错,后面可根据生成器传参
def func1(): # 创建一个生成器对象
for i in range(1, 3):
x = yield i # 类似于return和暂停,下次next时从这个位置开始,这里的x就是send方法传递的参数
s = x + 10
print("s:{}".format(s))
print("*"*40)
f1 = func1()
# print(next(f))
print(f1.send(None)) # 第一个值需要先传None
print(f1.send(10))
3、使用生成器创建斐波拉契数列
def func2(n):
a, b = 0, 1
for i in range(n):
yield b
a, b =b, b+a
return "over"
f2 = func2(4)
try:
while True:
print(f2.__next__())
except StopIteration as e: # 接收报错
print(e)
4、生成器在多任务切换时应用
def test1(): # 创建生成器
for i in range(1, 5):
print("this is test1 {}".format(i))
yield
def test2():
for i in range(1, 5):
print("this is test2 {}".format(i))
yield
def test3():
for i in range(1, 5):
print("this is test3 {}".format(i))
yield
t1 = test1() # 创建生成器对象
t2 = test2()
t3 = test3()
try: # 取出生成器中的元素
while True:
t1.__next__()
t2.__next__()
t3.__next__()
except StopIteration:
pass
二、可迭代的
概念:
Python中的迭代是指通过重复执行的代码处理相似的数据集的过程,并且本次迭代的处理数据要依赖上一次的结果继续往下做,上一次产生的结果为下一次产生结果的初始状态,如果中途有任何停顿,都不能算是迭代。
可迭代对象有:列表、元组、字典、字符串
判断一个对象是不是可迭代的可以同下面方式
from collections import Iterable
print(isinstance(对象, Iterable)) # 判断是否为可迭代的
# 如果输出为True表示为可迭代,False则表示不可迭代
三、迭代器
概念:
迭代,顾名思义就是重复做一些事很多次(就现在循环中做的那样)。迭代器是实现了__next__()方法的对象(这个方法在调用时不需要任何参数),它是访问可迭代序列的一种方式,通常其从序列的第一个元素开始访问,直到所有的元素都被访问才结束。 [注意]:迭代器只能前进不能后退
[迭代器的优点]:
使用迭代器不要求事先准备好整个迭代过程中的所有元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后元素可以不存在或者被销毁。因此迭代器适合遍历一些数量巨大甚至无限的序列。
判断一个对象是否为迭代器
from collections import Iterator
print(isinstance(对象, Iterator)) # 判断是否为迭代器
# 如果输出为True表示为迭代器,False则表示不是迭代器
可迭代的转迭代器
可以通过iter()函数来转换,注意:
- 转换后的对象为迭代器
- 转化后获取元素需要通过next()来获取
- 转换后无法像之前一样通过print查看所有元素
from collections import Iterable, Iterator
list1 = ['w', 'c', 'g']
print(isinstance(list1, Iterator)) # False
list2 = iter(list1)
print(isinstance(list2, Iterator)) # True
可迭代的、迭代器、生成器的关系