python中生成器,迭代器是一个难点,总结:
迭代器:
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
迭代器的特点: 节省内存,惰性运算,一次性取值,只能按顺序取
for循环和迭代器的关系:
无论是可迭代的还是迭代器都可以被for循环
如果直接循环迭代器,循环一次就没有了
如果循环的非迭代器,每一次循环都相当于从头到尾的循环 是因为在for循环中的所有非迭代器都会通过iter生成一个新的迭代器
迭代器最重要的一个作用就是节省内存
Python中提供的生成器:
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
def func(): print('hello') yield 1 g = func() # 调用"生成器函数" print(g) # g generator(生成器) # 调用就不会执行这个函数,而是返回一个生成器 print(dir(g)) # g是一个迭代器 # 所有的生成器都是迭代器
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器中也会用到send/yield from 下面我举例子会好理解一点
比如很常见的计算平均值的函数
def cal_avg(): # 定义一个函数 sum_n = 0 # 定义一个求和变量sum_n count = 0 # 定义一个计数器 while True: # while 循环 num = yield input('请输入数:') # 把用户输入的数赋值给变量num sum_n += int(num) # 每循环一次把num相加后的值赋给sum_n count += 1 # 计数器加一 yield sum_n/count # yield 停止符 也是一个记录符 记录求的平均值 g = cal_avg() # 调用生成器函数 for i in g: # 对g使用for循环 i接受了用户输入的值 a = g.send(i) # send函数(用send之前要用__next__或者for建立管道) 算出的平均值赋值给a 同时send一个i给第一个yield print(a) # 最终打印a 就是算出的平均值
如果函数中的yield要接收参数,那么应该使用send传值
如果函数中的yield不需要接收参数,那么应该使用next即可
yield from 的使用方法:
def func(): l1 = [1,2,3] s2 = 'abc' yield from l1 yield from s2 g = func() for i in g: print(i) 2 a b c