python cookbook学习笔记(2)

第7章: 函数

连载中......


7.11小节

内联回调函数

>函数1

#使用异步
def apply_async(func, args, *, callback):
    #Compute the result
    result = func(*args)

    #Invoke the callback with the result
    callbace(result)
  • 仔细观察,apply_async函数的参数(第二个位置和第三个位置)。

>脚本1

from queue import Queue
from functools import wraps

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)
        result_queue = Queue()
        result_queue.put(None)
        while True:
            result = result_queue.get()
            try:
                a = f.send(result)        #f是一个生成器所以会有send方法,这里的send把result传到了生成器f的内部,并且推动了生成器f的运行。
                apply_async(a.func, a.args, callback=result_queue.put)
            except StopIteration:
                break
    return wrapper

def add(x, y):
    return x + y

@inlined_async
def test():
    r = yield Async(add, (2, 3))   #r得到了装饰器send给它的result参数
    print(r)
    r = yield Async(add, ('hello', 'world'))
    print(r)
    for n in range(10):
        r = yield Async(add, (n, n))
        print(r)
    print('Goodbye')

#调用test
test()
#返回结果
5
helloworld
0
2
4
6
8
10
12
14
16
18
Goodbye

例子解析:

  • put() : 在队列尾部添加一个数值
  • get() : 在队列头部删除一个数值
  • test()函数的执行是从它的装饰器开始的,然后在while True循环中一次一次的解开yeild,而且仔细观察可以发现,test每一个yield的对象都是Async类的实例,这说明了外层的装饰器中的a变量保存的是一个Async对象。

讨论:

  • 回调函数,就是将计算挂起,然后在稍后的某个时刻计算得到了恢复,这一点非常自然的同生成器对应了起来。具体的来说就是yield会生成一个值然后就挂起,,后续调用生成器的__next__()或者send()方法会使得它再次启动

7.12

访问定义在闭包内的变量

def sample():
    n = 0
    # Closure function
    def func():
        print('n=', n)   #可以见到全局变量n

    # Accessor methods for n
    def get_n():
        return n

    def set_n(value):
        nonlocal n
        n = value

    # Attach as function attributes,给闭包的函数func设置属性
    func.get_n = get_n
    func.set_n = set_n
    return func

使用这个函数:

>>> f = sample()
>>> f()
n= 0
>>> f.set_n(10)
>>> f()
n= 10
>>> f.get_n()
10
>>>

脚本2

import sys
class ClosureInstance:
    def __init__(self, locals=None):
        if locals is None:
            locals = sys._getframe(1).f_locals

        # Update instance dictionary with callables
        self.__dict__.update((key,value) for key, value in locals.items()
                            if callable(value) )
    # Redirect special methods
    def __len__(self):
        return self.__dict__['__len__']()

# Example use
def Stack():
    items = []
    def push(item):
        items.append(item)

    def pop():
        return items.pop()

    def __len__():
        return len(items)

    return ClosureInstance()

例子解释:

  • locals对象是字典

你可能感兴趣的:(python cookbook学习笔记(2))