python回调函数的使用方法,python中的回调函数
0x00概述编程分为两类:系统编程和应用编程。所谓系统编程,简单来说就是写一个库;而应用编程就是用各种编写好的库来编写具有一定功能的程序,也就是应用。系统程序员会留一些接口,也就是API(应用编程接口),给自己的库,供程序员使用。所以在抽象层的图中,库位于应用程序的底部。
程序运行时,一般情况下,应用程序会经常通过API调用库中预先准备好的函数。然而,有些库函数要求应用程序先传递一个函数给它,以便它能在正确的时间被调用来完成目标任务。这个被传入然后被调用的函数叫做回调函数。
比如有一家酒店提供叫醒服务,但是要求旅客自己决定叫醒方式。你可以打电话到房间,或者你可以派服务员来敲门。如果睡死了,又怕耽误事,也可以要求往头上浇一盆水。这里的“唤醒”行为是由酒店提供的,相当于库函数,但唤醒方式是由旅客决定并告知酒店的,这就是回调函数。旅客告诉酒店如何叫醒自己的动作,也就是把回调函数转移到仓库函数的动作,叫做注册一个回调函数。如下图(图片来源:维基百科):
如您所见,回调函数通常与应用程序处于同一抽象级别(因为传入哪种回调函数是在应用程序级别决定的)。回调就变成了对底层的高层调用,底层回去调用高层流程。(我觉得)这应该是回调最早的应用,也是如此命名的原因。
0x01回调机制的优点从上面的例子可以看出,回调机制提供了很大的灵活性。请注意,从现在开始,我们把图中的库函数重新命名为中间函数,因为回调不仅仅用在应用程序和库之间。任何时候,只要你想获得类似上述情况的灵活性,都可以使用回调。
这种灵活性是如何实现的?回调乍一看似乎只是函数之间的调用,但仔细考虑,我们可以发现两者的一个关键区别:在回调中,我们使用某种方式将回调函数像参数一样传入中间函数。可以理解为在传入一个回调函数之前,中间函数是不完整的。换句话说,程序可以通过在运行时注册不同的回调函数来决定和改变中间函数的行为。这比简单的函数调用灵活得多。请看下面这个用Python写的回调的简单例子:
even.py
#回调函数1
#生成2k形式的偶数
双精度定义(x):
返回x * 2
#回调函数2
#生成4k形式的偶数
定义四倍(x):
返回x * 4
回调_演示. py
甚至从进口*
#中间函数
#接受生成偶数的函数作为参数
#返回一个奇数
def getOddNumber(k,getEvenNumber):
返回1 getEvenNumber(k)
#启动功能,这里是程序的主要功能
def main():
k=1
#当需要生成2k 1形式的奇数时
i=getOddNumber(k,double)
打印(一)
#当需要4k 1形式的奇数时
i=getOddNumber(k,四倍)
打印(一)
#当需要8k-1形式的奇数时
i=getOddNumber(k,x:x * 8)
打印(一)
if __name__==__main__ :
主()
运行callback_demp.py,输出如下:
三
五
九
上面的代码中,传递给getOddNumber 的回调函数不同,其性能也不同,这就是回调机制的优势。值得一提的是,上面第三个回调函数是匿名函数。
0x02容易被忽略的第三方从上面的讨论中知道,中间函数和回调函数是回调的两个必要部分,但是人们往往忽略了回调中第三个重要的点,那就是中间函数的调用者。在大多数情况下,这个调用者可以等同于程序的主函数,但是为了说明区别,我在这里称它为启动函数(如上面代码中的注释所示)。
之所以特别强调这个第三方,是因为我在网上看相关文章时得到一个印象,很多人把它简单理解为两个人之间的来回通话。比如很多中文网页在解释“回拨”的时候,都会提到这样一句话:“你给我打电话,我给你回电话。”我还没有找到这个英语句子的来源。个人猜测,很多人把启动函数和回调函数当成了一个,大概有两个原因:一是“回调”这个名字可能有误导性;第二,什么样的回调函数传递给中间函数,是在初始函数中决定的。其实回调不是你中有我的互动,而是ABC的三方联动。有了这个清晰的概念,在自己的代码中实现回调时就不容易混淆错误。
另外,回调其实也有两种:阻塞式回调和延期式回调。两者的区别在于:在阻塞回调中,回调函数的调用必须发生在初始函数返回之前;在延迟回调中,回调函数可能在初始函数返回后被调用。我不打算在这里深入讨论这两种概率。之所以提出它们,是为了说明强调初始功能的重要性。网上很多文章,在提到这两个概念的时候,只是笼统的说阻塞回调发生在主旋律函数返回之前,而没有明确主旋律函数是起始函数还是中间函数,比较混乱,这里专门解释一下。还请注意,本文中的例子都是阻塞回调。延迟回调通常涉及到多线程,我还没有完全理解,这里就不多说了。
涉及
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。