Python技巧(6):cookbook学习笔记

时间:2022-04-17 06:40:22

(1)

可以采取传递默认参数的方式来绑定变量

x = 1
f = lambda y,x=x:x+y
print(f(1))
x = 2
print(f(1))

创建一个函数集合的时候可能会这样写:

funcs = {n:lambda x: x+n for n in range(5)}

发现n是不能被绑定在函数体里面的,正确的姿势是:

funcs = {n:lambda x,n=n: x+n for n in range(5)}

(2)

如果你想使用某一个函数作为callable对象,但是它的参数太多导致出错。你可以想办法固定下几个参数。怎么做呢?一般的办法是可以自己写一个wrapper函数将你的函数包装一下,但是这样显得小题大作。比较优雅的写法是利用functools.partial这个函数。它实现上述的功能,但是高效而且简洁。

def f(a,b,c,d):
pass
from functools import partial
f = partial(f, 1) # a = 1
f2 = partial(f, 1, 2, d=42) # a = 1, b = 2, d = 42

(3) :我们想让使用了回调函数的代码看起来更像普通流程的代码。下面利用了装饰器来进行包装。将异步计算的工作交给async_apply来实现,注意Queue是可以跨进程通信的,所以无论怎样只要上一次的结果没有放入result_queue,就不会进行下一次计算。

def apply_async(func,args,*,callback):

result = func(*args)#有可能中断
callback(result)
class Async:
def __init__(self,func,args):
self.func = func
self.args = args
def inlined_async(func):
@wraps(func)
def wrapper(*args):
f = func(*args)#get a generator
result_queue = Queue()
result_queue.append(None)
while True:
result = result_queue.get()#wait the result to be generated
try:
a = f.send(result)
apply_async(a.func,a.args,callback = result_queue.put)# callback will put a.func(*a.args) in result_queue
except StopIteration:
break
return wrapper
def add(x,y):
import time
time.sleep(1)
print('done')
return x+y
@inlined_async
def test():
r = yield Async(add,(2,3))#generate the function and args you want async_apply to compute
print(r)
r = yield Async(add,('hello','world'))
print(r)
for n in range(15):
r = yield Async(add,(n,n))#async to compute:异步计算
print(r)#print what we get
print('Goodbyy')