迭代器
- 可迭代(Iterable):直接作用于for循环的变量
迭代器(Iterator):不但可作用于for循环,还可以被next调用
list是典型的可迭代对象,但不是迭代器
通过isinstance判断
iterable和iterator可以转换
通过iter函数
#可迭代
l = [ i for i in range(10)]
#list是可以迭代的,但不是迭代器
for idx in l:
print(idx)
# range是个迭代器
for i in range(5):
print(i)
#list
from collections import Iterable
l1 = [1,2,3,4,5]
print(isinstance(l1,Iterable))
from collections import Iterator
print(isinstance(l1,Iterator))
生成器
generator:一边循环一遍计算下一个元素的算法
需要满足三个条件
每次调用都生产出for 循环需要的下一个元素
如果达到最后一个,爆出stopIteration异常
可以被next函数调用
如何生成一个生成器
直接使用
如果函数中包含yield,则这个函数就叫做生成器
next 调用函数,遇到yield返回
#直接使用生成器
L =[x*x for x in range(5)]#放在中括号是列表生成器
g = (x*x for x in range(5))#放在小括号中就是生成器
print(type(L))
print(type(g))
#函数案例
def odd():
print("Step 1")
print("Step 2")
print("Step 3")
return None
odd()
#生成器的案例
def odd():
print("Step 1")
yield 1
print("Step 2")
yield 2
print("Step 3")
yield 3
g= odd()
odd()
one = next(g)
print(one)
two = next(g)
print(two)
three = next(g)
print(three)
#for 循环生成器
def fib(max):
n,a,b = 0,0,1
while n <max:
yield b
a,b= b,a+b
n=n+1
return 'done'
g=fib(5)
for i in range(6):
rst =next(g)
print(rst)
ge = fib(10)
'''生成器的典型用法是在for中使用
比较常见的典型生成器是range
'''
for i in ge:
print(i)
协程序
- 历史进程
-3.4引入协程,用yield实现
- 3.5引入协程语法
- 实现的协程比较好的包有asyncio,tornado,gevent - 定义:协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口的点在不同位置暂停或者开始执行程序.
- 从技术角度讲,协程就是一个你可以暂停执行的函数,或者干脆把协程理解成生成器.
- 协程的实现:
- yield返回
- send调用
#协程代码案例1
def simple_coroutine():
print('->start')
x= yield
print('->recived',x)
sc=simple_coroutine()
print(1111)
#可以使用sc.send(none),效果一样
next(sc)
print(22222)
sc.send('dfd')
- 协程的四个状态
- inspect.getgenratorstate()函数确定,该函数会返回下述字符中的一个:
- GEN_CREATED:等待开始执行
- GEN_SUSPENED:在yield表达式处暂停
- GEN_CLOSED:执行结束
- nex预激活(prime)
-代码案例V2
#案例V2,协程状态
def simple_coroutine(a):
print("start")
b=yield a
print("recived",a,b)
c = yield a+b
print("recived",a,b,c)
#runc
sc =simple_coroutine(5)
aa=next(sc)
print(aa)
bb=sc.send(6)
print(bb)
cc=sc.send(7)
print(cc)
协程终止
-
协程中未处理的异常会往上冒泡,传给next函数或者send方法的调用方(即触发协程的对象)
-
停止协程对的一种方法:发送某个哨符值,让协程退出.内置的NONE和ELLIPSIS等敞亮经常用作哨符值==.
-
yield from
- 调用协程为了得到返回值,协程必须正常终止
- 生成器正常终止会发出stopIteration异常,异常对象的vlaue属性保存返回值
- yield from从内部捕获 StopIteration异常
- 案例V3
def gen():
for c in "AB":
yield c
#list 直接生成器作为参数
print(list(gen()))
def gen_new():
yield from "AB"
print(list(gen_new()))
- 委派生成器
- 包含yield from表达式的生成器函数
- 委派生成器在yield from表达式暂停,调用方法可以直接把数据发给子生成器
- 子生成器把产生出的值发给调用方
- 子生成器在最后,解释器会抛出StopIteration异常
- 案例V4
案例v4
#案例V4
from collections import namedtuple
Result=namedtuple('Result','average number')
def subaverager():#子生成器
total = 0.0
number = 0
average = None
while True:
term = yield
if term is None:
break
total += term
number += 1
average=total/number
return Result(average,number)
def averager(results,key):#委派生成器
while True:
results[key]=yield from subaverager()
def main(grouper):
results={}
for key,group in grouper.items():
term = averager(results,key)
next(term)
for value in group:
term.send(value)
term.send(None)
print(results)#调试使用
result(results)
def result(results):
for key,value in results.items():
gender,unit=key.split(';')
print('{} {} averaging {:.2f} {}.'.format(
value.number,gender,value.average,unit))
data = {
'girls;kg':
[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
'girls;m':
[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
'boys;kg':
[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys;m':
[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}
if __name__=='__main__':
main(data)