## 直接使用生成器
L = [x * x for x in range(10)] # 放在中括号中是列表生成器
g = (x * x for x in range(10)) # 放在小括号中是生成器
print(type(L))
print(type(g))
><class 'list'>
<class 'generator'>
# for循环调用生成器
def fib(max):
n, a, b = 0, 0, 1 # 注意写法
while n < max:
print(b)
a, b = b, a + b # 注意写法
n += 1
return 'Done'
fib(5)
>1
1
2
3
5
# 斐波那契额数列的生成器写法
def fib(max):
n, a, b = 0, 0, 1 # 注意写法
while n < max:
yield b
a, b = b, a + b # 注意写法
n += 1
# 需要注意,爆出异常是的返回值是return的返回值
return 'Done'
g = fib(5)
for i in range(6):
rst = next(g)
print(rst)
>1
1
2
3
5
.....
StopIteration: Done
## return from
def gen():
for c in 'AB':
yield c
## list直接用生成器作为参数
print(list(gen()))
def gen_new():
yield from 'AB'
print(list(gen_new()))
>['A', 'B']
['A', 'B']
# 委派生成器
from collections import namedtuple
'''
解释:
1. 外层 for 循环每次迭代会新建一个 grouper 实例,赋值给 coroutine 变量; grouper 是委派生成器。
2. 调用 next(coroutine),预激委派生成器 grouper,此时进入 while True 循环,调用子生成器 averager 后,在 yield from 表达式处暂停。
3. 内层 for 循环调用 coroutine.send(value),直接把值传给子生成器 averager。同时,当前的 grouper 实例(coroutine)在 yield from 表达式处暂停。
4. 内层循环结束后, grouper 实例依旧在 yield from 表达式处暂停,因此, grouper函数定义体中为 results[key] 赋值的语句还没有执行。
5. coroutine.send(None) 终止 averager 子生成器,子生成器抛出 StopIteration 异常并将返回的数据包含在异常对象的value中,yield from 可以直接抓取 StopItration 异常并将异常对象的 value 赋值给 results[key]
'''
ResClass = namedtuple('Res', 'count average')
# 子生成器
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield
# None是哨兵值
if term is None:
break
total += term
count += 1
average = total / count
return ResClass(count, average)
# 委派生成器
def grouper(storages, key):
while True:
# 获取averager()返回的值
storages[key] = yield from averager()
# 客户端代码
def client():
process_data = {
'boys_2': [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys_1': [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46]
}
storages = {}
for k, v in process_data.items():
# 获得协程
coroutine = grouper(storages, k)
# 预激协程
next(coroutine)
# 发送数据到协程
for dt in v:
coroutine.send(dt)
# 终止协程
coroutine.send(None)
print(storages)
# run
client()
>{'boys_2': Res(count=9, average=40.422222222222224), 'boys_1': Res(count=9, average=1.3888888888888888)}
import time,re
import os,datetime
from concurrent import futures
data = ['1','2']
def wait_on(argument):
print(argument)
time.sleep(2)
return "ok"
ex = futures.ThreadPoolExecutor(max_workers=2)
for i in ex.map(wait_on,data):
print(i)
Future
- 未来需要完成的任务
- future 实例由Excutor.submit创建
from concurrent.futures import ThreadPoolExecutor as Pool
from concurrent.futures import as_completed
import requests
URLS = ['http://qq.com', 'http://sina.com', 'http://www.baidu.com', ]
def task(url, timeout=10):
return requests.get(url, timeout=timeout)
with Pool(max_workers=3) as executor:
future_tasks = [executor.submit(task, url) for url in URLS]
for f in future_tasks:
if f.running():
print('%s is running' % str(f))
for f in as_completed(future_tasks):
try:
ret = f.done()
if ret:
f_ret = f.result()
print('%s, done, result: %s, %s' % (str(f), f_ret.url, len(f_ret.content)))
except Exception as e:
f.cancel()
print(str(e))