Python进阶篇--如何实现回调

看到标题大家可能都会觉得很简单,但是事实并非如此,接下来我们一起细细看来。

第一种回调:看到标题后你的第一反应

def handler(x):
    print("The result is ", x)


def add(a, b):
    return a + b


def task_async(func, args,  *, callback=None):
    result = func(*args)
    callback(result)


if __name__ == "__main__":
    task_async(add, (2, 3), callback=handler)

超级简单的回调模型。

第二种回调:带外部状态的回调

class RequestHandler:
    def __init__(self):
        self.sequence = 0

    def handler(self, result):
        self.sequence += 1
        print("[{}] Got: {}".format(self.sequence, result))


def add(a, b):
    return a + b


def task_async(func, args,  *, callback=None):
    result = func(*args)
    callback(result)


if __name__ == "__main__":
    request = RequestHandler()
    task_async(add, (2, 3), callback=request.handler)
    task_async(add, ("hi", " nihao"), callback=request.handler)

通过类变量来让回调函数带上外部状态
另外,我们还可以通过闭包来实现。

def make_handler():
    sequence = 0

    def handler(result):
        nonlocal sequence
        sequence += 1
        print("[{}] Got {}".format(sequence, result))

    return handler


def add(a, b):
    return a + b


def task_async(func, args,  *, callback=None):
    result = func(*args)
    callback(result)


if __name__ == "__main__":
    handler = make_handler()
    task_async(add, (2, 3), callback=handler)
    task_async(add, ("hi", " nihao"), callback= handler)

其实闭包和简单的类时可以向上面互换的。

第三种回调:利用协程(高端大气)

def make_handler():
    sequence = 0
    while True:
        result = yield
        sequence += 1
        print("[{}] Got {}".format(sequence, result))


def add(a, b):
    return a + b


def task_async(func, args,  *, callback=None):
    result = func(*args)
    callback(result)


if __name__ == "__main__":
    handler = make_handler()
    next(handler)
    task_async(add, (2, 3), callback=handler.send)
    task_async(add, ("hi", " nihao"), callback= handler.send)

好了,协程这个非常巧妙。

第四种回调:内联回调,基于协程和生成器

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)
                task_async(a.func, a.args, callback=result_queue.put)
            except StopIteration:
                break
    return wrapper


def add(a, b):
    return a + b


@inlined_async
def test():
    r = yield Async(add, (2, 3))
    print(r)
    r = yield Async(add, ("hi", "hajimemashite"))
    print(r)

    for n in range(10):
        r = yield Async(add, (n, n))
        print(r)

    print("Goodbye")


def task_async(func, args,  *, callback=None):
    result = func(*args)
    callback(result)

这个例子略微复杂,需要的python知识比较多。通过这样设计,所有的回调都在内部进行消化。使用起来感觉不到回调。

根据第一性原理,凡事需要思考本质。其实回调的本质是一个生产者和消费者模型的设计。这样我们就可以拓开思路。Do not repeat yourself.

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值