美文网首页
带额外状态信息的回调函数

带额外状态信息的回调函数

作者: 码男将将 | 来源:发表于2021-11-25 17:23 被阅读0次

前言:

之前了解单方法类变为函数的方案后一直在想怎么进行应用;现在发现一个给函数(方法)增加状态信息的案例,同样来自python cook! codeMan奉上.

回调函数callback

回调函数就是一个被作为参数传递的函数!
1.定义一个回调函数;
2.提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
3.当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
Python没有指针这个说法一般都是说函数名.简单来说就是定义一个函数,然后将这个函数的函数名传递给另一个函数做参数,以这个参数命名的函数就是回调函数。

# 执行函数
def apply_async(*args, callback):
  callback(args)

#回调函数
def print_result(args):
  print('Got:', args)

if __name__ == "__mian__":
  apply_async(1,2,"a","-", callback=print_result)

以上为回调函数的基本用法.回调函数用途超广业务方面:事件处理器、等待后台任务完成后回调;系统编程中:线程、进程和定时器中都用到了回调函数.

问题

print_result() 函数仅仅只接受一个参数 result .不能再传入其他信息.
而当你想让回调函数访问其他变量或者特定环境的变量值的时候就会遇到麻烦。

解决方案1-类实现:

使用一个绑定方法来代替一个简单函数

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

class ResultHandler:
  def __init__(self):
    self.sequence = 0
  def handler(self, result):
    self.sequence += 1
    print('[{}] Got: {}'.format(self.sequence, result))

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

if __name__ == "__main__":
  r = ResultHandler()
  apply_async(add, (2, 3), callback=r.handler)  # Got: 5
  apply_async(add, ('hello', 'world'), callback=r.handler) #Got: helloworld

解决方案2-闭包实现

作为类的替代,可以使用一个闭包捕获状态值.优雅版

def apply_async(func, args, *, callback):
  result = func(*args)
  callback(result)
def make_handler():
  sequence = 0
  def handler(result):
    nonlocal sequence
    sequence += 1
    print('[{}] Got: {}'.format(sequence, result))
  return handler

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

if __name__ == "__main__":
  handler = make_handler()
  apply_async(add, (2, 3), callback=handler)  # Got: 5
  apply_async(add, ('hello', 'world'), callback=handler) #Got: helloworld

解决方案3-协程解决

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

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

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

if __name__ == "__main__":
  handler = make_handler()
  next(handler) # Advance to the yield
  apply_async(add, (2, 3), callback=handler.send)  # Got: 5
  apply_async(add, ('hello', 'world'), callback=handler.send) #Got: helloworld

通过handler的send把add的结果也就是result待会yield的位置赋值给result_new

结论:

三种方式的优缺点:
使用类的实例属性进行进行存取,需要手动记录代码略显冗余
使用闭包进行存取,所有使用到的变量都可自动捕获,代码优雅很多.不过需要注意的是内部函数访问外部函数变量时一定要nonlocal声明不然代码会报错
使用协程方式代码最为简洁一个函数搞定,不过需要对协程的工作原理理解清晰(它的逻辑就抽象很多).不然容易忘掉添加next()或者不理解send干了什么.

写在后面

作者说为何要这么做:
基于回调函数的软件通常都有可能变得非常复杂。一部分原因是回调函数通常会
跟请求执行代码断开。因此,请求执行和处理结果之间的执行环境实际上已经丢失了。
如果你想让回调函数连续执行多步操作,那你就必须去解决如何保存和恢复相关的状
态信息了。

相关文章

  • 闭包(保存变量) --在回调函数中携带额外状态的几种方法

    问题: 希望编写回调函数可以携带额外的状态以便在回调函数内部使用 首先定义一个回调函数: 使用示例: 有些时候我们...

  • Keras常用回调函数

      回调函数是一组在训练的特定阶段被调用的函数集,你可以使用回调函数来观察训练过程中网络内部的状态和统计信息。通过...

  • JavaScript函数_08回调函数

    回调函数 回调函数(回调),当我们把某个函数作为参数传递给另一个函数的时候,这个函数就是回调函数 回调函数的基本写...

  • Promise

    回调 把一个函数A传给另一个函数B调用,那么A就是回调函数。 回调地狱 回调套回调套回调套回调套回调套回调套回调....

  • 回调函数解析

    一个普通的带函数的参数: 回调函数 回调包含同步回调和异步回调。只不过异步回调用的多一些而已。 回来讲为什么js是...

  • 回调函数与promise

    回调 把一个函数A传给另一个函数B调用,那么A就是回调函数 具名回调写法 匿名回调写法 多层嵌套的匿名回调(回调地...

  • 回调函数与promise

    回调 把一个函数A传给另一个函数B调用,那么A就是回调函数 具名回调写法 匿名回调写法 多层嵌套的匿名回调(回调地...

  • 从以太坊交易日志中监听智能合约事件event

    以太坊智能合约中,有一类特殊的回调函数,没有函数体,以大写字母开头,一般用来记录函数状态,这类回调函数称为事件ev...

  • JavaScript系列之回调函数callback

    JavaScript系列之回调函数callback JavaScript回调函数的使用是很常见的,引用官方回调函数...

  • node系列扯犊子之八Events模块

    起因:回调函数模式让 Node 可以处理异步操作。但是,为了适应回调函数,异步操作只能有两个状态:开始和结束。对于...

网友评论

      本文标题:带额外状态信息的回调函数

      本文链接:https://www.haomeiwen.com/subject/yeodtrtx.html