# -*- encoding: utf-8 -*-
from collections import namedtuple
'''
第40条: 考虑用协程来并发地运行多个函数
关键:
1 线程
缺点:
1)多线程代码难懂
2)线程需要占用大量内存,每个线程大约8MB
3)线程启动开销较大
2 协程
作用: 使python程序看上去同时运行多个函数
实现方式: 对生成器地扩展
优点: 占据地内存大约1KB
原理:
1)生成器函数执行到yield表达式,消耗生成器的代码,通过send方法给
生成器传回一个值,生成器收到了send函数传进来的这个值后,会视为是yield
表达式的执行结果
2)协程是独立函数,消耗外部环境传入的输入数据,并产生输出结果
与线程的不同点:
协程会在生成器函数中的每个yield表达式那里暂停,等到外界再次
调用send方法,才会继续执行到下一个yield表达式。
注意: 在生成器调用send方法前,需要先调用一次next函数,将生成器
进入到第一条yield表达式
3 yield from
1)python2中没有yield from表达式
把两个生成器组合起来,需要在委派给另一个线程的地方,多写一层循环
2)python2的生成器不支持return语句,需要定义自己的异常类型。
并在需要返回某个值的时候,抛出该异常
4 总结
协程让程序卡上去能同时运行大量函数
对于生成器内的yield表达式来说,外部代码通过send方法传递给生成器
的那个值,就是该表达式具备的值
协会次呢个可以把程序逻辑和交互代码分离
python2不支持yield from,也不支持在生成器内通过return语句向外界返回某个值。
参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''
def myCoroutine():
while True:
received = yield
print "Received: {value}".format(
value=received
)
def useCoroutine():
it = myCoroutine()
'''
在生成器调用send方法前,需要先调用一次next函数,将生成器
进入到第一条yield表达式
'''
next(it)
it.send('First')
it.send('Second')
def minimize():
current = yield
while True:
value = yield current
current = min(value, current)
def useMinimize():
it = minimize()
next(it)
print it.send(10)
print it.send(4)
print it.send(22)
print it.send(-1)
ALIVE = "*"
EMPTY= "-"
Query = namedtuple('Query', ('y', 'x'))
def countNeighbors(y, x):
north = yield Query(y + 1, x + 0)
northEast = yield Query(y + 1, x + 1)
east = yield Query(y, x + 1)
eastSouth = yield Query(y - 1, x + 1)
south = yield Query(y - 1, x)
westSouth = yield Query(y - 1, x - 1)
west = yield Query(y, x - 1)
westNorth = yield Query(x - 1, y + 1)
neighborStates = [
north, northEast,
east, eastSouth,
south, westSouth,
west, westNorth
]
count = 0
for state in neighborStates:
if state == ALIVE:
count += 1
yield count
def useCountNeighbors():
it = countNeighbors(10, 5)
q1 = next(it)
print "First yield: {value}".format(
value=q1
)
q2 = it.send(ALIVE)
print "Second yield: {value}".format(
value=q2
)
q3 = it.send(ALIVE)
print "Third yield: {value}".format(
value=q3
)
q4 = it.send(EMPTY)
print "Fourth yield: {value}".format(
value=q4
)
q5 = it.send(EMPTY)
print "Fifth yield: {value}".format(
value=q5
)
q6 = it.send(EMPTY)
print "Sixth yield: {value}".format(
value=q6
)
q7 = it.send(EMPTY)
print "Seventh yield: {value}".format(
value=q7
)
q8 = it.send(EMPTY)
print "Eighth yield: {value}".format(
value=q8
)
try:
count = it.send(EMPTY)
print "count: {value}".format(value=count)
except StopIteration as e:
print "Count: {value}".format(
value=e.value
)
# Transition = namedtuple('Transition', ('y', 'x', 'state'))
#
# def gameLogic(state, neighbors):
# if state == ALIVE:
# if neighbors < 2:
# return EMPTY
# elif neighbors > 3:
# return EMPTY
# else:
# if neighbors == 3:
# return ALIVE
# return state
#
# '''
# 作用: 通过参数接收当前细胞的网格坐标,对坐标产生Query对象,
# 以查询本细胞的初始状态。接下来运行countNeighbots协程,检查
# 本细胞周边的其他细胞,最后运行gameLogic函数,判断本细胞
# 在下一轮的状态。最后生成Transition对象,把本细胞
# 在下一轮所应有的状态,告诉外部代码
# '''
# def stepCell(y, x):
# state = yield Query(y, x)
# neighbors = yield from countNeighbors(y, x)
# nextState = gameLogic(state, neighbors)
# yield Transition(y, x, nextState)
#
#
# def useStepCell():
# it = stepCell(10, 5)
# q0 = next(it)
# print "Me: {value}".format(value=q0)
# q1 = it.send(ALIVE)
# print "Q1: {value}".format(value=q1)
# t1 = it.send(EMPTY)
# print "Outcome: {value}".format(value=t1)
def delegated2():
yield 1
yield 2
def composed2():
yield 'A'
for value in delegated2():
yield value
yield 'B'
class MyReturn(Exception):
def __init__(self, value):
self.value = value
def delegated():
yield 1
raise MyReturn(2)
yield 'Not reached'
def composed():
try:
for value in delegated():
yield value
except MyReturn as e:
output = e.value
yield output * 4
def process():
useCoroutine()
useMinimize()
# useCountNeighbors()
print list(composed())
if __name__ == "__main__":
process()
Effective Python 读书笔记: 第40条: 考虑用协程来并发地运行多个函数
猜你喜欢
转载自blog.csdn.net/qingyuanluofeng/article/details/88962733
今日推荐
周排行