亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python回調(diào)函數(shù)用法實(shí)例

系統(tǒng) 2034 0

Python回調(diào)函數(shù)用法實(shí)例

?

?

作者:no.body
鏈接:https://www.zhihu.com/question/19801131/answer/27459821

什么是回調(diào)函數(shù)?

我們繞點(diǎn)遠(yuǎn)路來回答這個問題。

編程分為兩類:系統(tǒng)編程(system programming)和應(yīng)用編程(application programming)。所謂系統(tǒng)編程,簡單來說,就是編寫 ;而應(yīng)用編程就是利用寫好的各種庫來編寫具某種功用的程序,也就是 應(yīng)用 。系統(tǒng)程序員會給自己寫的庫留下一些接口,即API(application programming interface,應(yīng)用編程接口),以供應(yīng)用程序員使用。所以在抽象層的圖示里,庫位于應(yīng)用的底下。

當(dāng)程序跑起來時(shí),一般情況下,應(yīng)用程序(application program)會時(shí)常通過API調(diào)用庫里所預(yù)先備好的函數(shù)。但是有些庫函數(shù)(library function)卻要求應(yīng)用先傳給它一個函數(shù),好在合適的時(shí)候調(diào)用,以完成目標(biāo)任務(wù)。這個被傳入的、后又被調(diào)用的函數(shù)就稱為 回調(diào)函數(shù) (callback function)。

打個比方,有一家旅館提供叫醒服務(wù),但是要求旅客自己決定叫醒的方法。可以是打客房電話,也可以是派服務(wù)員去敲門,睡得死怕耽誤事的,還可以要求往自己頭上澆盆水。這里,“叫醒”這個行為是旅館提供的,相當(dāng)于庫函數(shù),但是叫醒的方式是由旅客決定并告訴旅館的,也就是回調(diào)函數(shù)。而旅客告訴旅館怎么叫醒自己的動作,也就是把回調(diào)函數(shù)傳入庫函數(shù)的動作,稱為 登記回調(diào)函數(shù) (to register a callback function)。如下圖所示(圖片來源:維基百科):

? Python回調(diào)函數(shù)用法實(shí)例_第1張圖片

可以看到,回調(diào)函數(shù)通常和應(yīng)用處于同一抽象層(因?yàn)閭魅胧裁礃拥幕卣{(diào)函數(shù)是在應(yīng)用級別決定的)。而回調(diào)就成了一個高層調(diào)用底層,底層再回過頭來調(diào)用高層的過程。(我認(rèn)為)這應(yīng)該是回調(diào)最早的應(yīng)用之處,也是其得名如此的原因。

?

回調(diào)機(jī)制的優(yōu)勢

從上面的例子可以看出,回調(diào)機(jī)制提供了非常大的靈活性。請注意,從現(xiàn)在開始,我們把圖中的庫函數(shù)改稱為 中間函數(shù) 了,這是因?yàn)榛卣{(diào)并不僅僅用在應(yīng)用和庫之間。任何時(shí)候,只要想獲得類似于上面情況的靈活性,都可以利用回調(diào)。

這種靈活性是怎么實(shí)現(xiàn)的呢?乍看起來,回調(diào)似乎只是函數(shù)間的調(diào)用,但仔細(xì)一琢磨,可以發(fā)現(xiàn)兩者之間的一個關(guān)鍵的不同:在回調(diào)中,我們利用某種方式,把回調(diào)函數(shù)像參數(shù)一樣傳入中間函數(shù)。可以這么理解,在傳入一個回調(diào)函數(shù)之前,中間函數(shù)是不完整的。換句話說,程序可以在運(yùn)行時(shí),通過登記不同的回調(diào)函數(shù),來決定、改變中間函數(shù)的行為。這就比簡單的函數(shù)調(diào)用要靈活太多了。請看下面這段Python寫成的回調(diào)的簡單示例:



`even.py`
                  
                    
                      #回調(diào)函數(shù)1

                      
                        #生成一個2k形式的偶數(shù)

                        
                          def 
                          
                            double
                            
                              (
                              
                                x
                                
                                  ): 
                                  
                                    return 
                                    
                                      x 
                                      
                                        * 
                                        
                                          2 
                                          
                                            #回調(diào)函數(shù)2 
                                            
                                              #生成一個4k形式的偶數(shù) 
                                              
                                                def 
                                                
                                                  quadruple
                                                  
                                                    (
                                                    
                                                      x
                                                      
                                                        ): 
                                                        
                                                          return 
                                                          
                                                            x 
                                                            
                                                              * 
                                                              
                                                                4 
                                                              
                                                            
                                                          
                                                        
                                                      
                                                    
                                                  
                                                
                                              
                                            
                                          
                                        
                                      
                                    
                                  
                                
                              
                            
                          
                        
                      
                    
                  
                

`callback_demo.py`
                  
                    
                      from 
                      
                        even 
                        
                          import 
                          
                            *


                            
                              #中間函數(shù) 
                              
                                #接受一個生成偶數(shù)的函數(shù)作為參數(shù) 
                                
                                  #返回一個奇數(shù) 
                                  
                                    def 
                                    
                                      getOddNumber
                                      
                                        (
                                        
                                          k
                                          
                                            , 
                                            
                                              getEvenNumber
                                              
                                                ): 
                                                
                                                  return 
                                                  
                                                    1 
                                                    
                                                      + 
                                                      
                                                        getEvenNumber
                                                        
                                                          (
                                                          
                                                            k
                                                            
                                                              ) 
                                                              
                                                                #起始函數(shù),這里是程序的主函數(shù) 
                                                                
                                                                  def 
                                                                  
                                                                    main
                                                                    
                                                                      (): 
                                                                      
                                                                        k 
                                                                        
                                                                          = 
                                                                          
                                                                            1 
                                                                            
                                                                              #當(dāng)需要生成一個2k+1形式的奇數(shù)時(shí) 
                                                                              
                                                                                i 
                                                                                
                                                                                  = 
                                                                                  
                                                                                    getOddNumber
                                                                                    
                                                                                      (
                                                                                      
                                                                                        k
                                                                                        
                                                                                          , 
                                                                                          
                                                                                            double
                                                                                            
                                                                                              ) 
                                                                                              
                                                                                                print
                                                                                                
                                                                                                  (
                                                                                                  
                                                                                                    i
                                                                                                    
                                                                                                      ) 
                                                                                                      
                                                                                                        #當(dāng)需要一個4k+1形式的奇數(shù)時(shí) 
                                                                                                        
                                                                                                          i 
                                                                                                          
                                                                                                            = 
                                                                                                            
                                                                                                              getOddNumber
                                                                                                              
                                                                                                                (
                                                                                                                
                                                                                                                  k
                                                                                                                  
                                                                                                                    , 
                                                                                                                    
                                                                                                                      quadruple
                                                                                                                      
                                                                                                                        ) 
                                                                                                                        
                                                                                                                          print
                                                                                                                          
                                                                                                                            (
                                                                                                                            
                                                                                                                              i
                                                                                                                              
                                                                                                                                ) 
                                                                                                                                
                                                                                                                                  #當(dāng)需要一個8k+1形式的奇數(shù)時(shí) 
                                                                                                                                  
                                                                                                                                    i 
                                                                                                                                    
                                                                                                                                      = 
                                                                                                                                      
                                                                                                                                        getOddNumber
                                                                                                                                        
                                                                                                                                          (
                                                                                                                                          
                                                                                                                                            k
                                                                                                                                            
                                                                                                                                              , 
                                                                                                                                              
                                                                                                                                                lambda 
                                                                                                                                                
                                                                                                                                                  x
                                                                                                                                                  
                                                                                                                                                    : 
                                                                                                                                                    
                                                                                                                                                      x 
                                                                                                                                                      
                                                                                                                                                        * 
                                                                                                                                                        
                                                                                                                                                          8
                                                                                                                                                          
                                                                                                                                                            ) 
                                                                                                                                                            
                                                                                                                                                              print
                                                                                                                                                              
                                                                                                                                                                (
                                                                                                                                                                
                                                                                                                                                                  i
                                                                                                                                                                  
                                                                                                                                                                    ) 
                                                                                                                                                                    
                                                                                                                                                                      if 
                                                                                                                                                                      
                                                                                                                                                                        __name__ 
                                                                                                                                                                        
                                                                                                                                                                          == 
                                                                                                                                                                          
                                                                                                                                                                            "__main__"
                                                                                                                                                                            
                                                                                                                                                                              : 
                                                                                                                                                                              
                                                                                                                                                                                main
                                                                                                                                                                                
                                                                                                                                                                                  () 
                                                                                                                                                                                
                                                                                                                                                                              
                                                                                                                                                                            
                                                                                                                                                                          
                                                                                                                                                                        
                                                                                                                                                                      
                                                                                                                                                                    
                                                                                                                                                                  
                                                                                                                                                                
                                                                                                                                                              
                                                                                                                                                            
                                                                                                                                                          
                                                                                                                                                        
                                                                                                                                                      
                                                                                                                                                    
                                                                                                                                                  
                                                                                                                                                
                                                                                                                                              
                                                                                                                                            
                                                                                                                                          
                                                                                                                                        
                                                                                                                                      
                                                                                                                                    
                                                                                                                                  
                                                                                                                                
                                                                                                                              
                                                                                                                            
                                                                                                                          
                                                                                                                        
                                                                                                                      
                                                                                                                    
                                                                                                                  
                                                                                                                
                                                                                                              
                                                                                                            
                                                                                                          
                                                                                                        
                                                                                                      
                                                                                                    
                                                                                                  
                                                                                                
                                                                                              
                                                                                            
                                                                                          
                                                                                        
                                                                                      
                                                                                    
                                                                                  
                                                                                
                                                                              
                                                                            
                                                                          
                                                                        
                                                                      
                                                                    
                                                                  
                                                                
                                                              
                                                            
                                                          
                                                        
                                                      
                                                    
                                                  
                                                
                                              
                                            
                                          
                                        
                                      
                                    
                                  
                                
                              
                            
                          
                        
                      
                    
                  
                

運(yùn)行`callback_demp.py`,輸出如下:
                  
                    3
5
9
                  
                

上面的代碼里,給`getOddNumber`傳入不同的回調(diào)函數(shù),它的表現(xiàn)也不同,這就是回調(diào)機(jī)制的優(yōu)勢所在。值得一提的是,上面的第三個回調(diào)函數(shù)是一個匿名函數(shù)。

易被忽略的第三方

通過上面的論述可知,中間函數(shù)和回調(diào)函數(shù)是回調(diào)的兩個必要部分,不過人們往往忽略了回調(diào)里的第三位要角,就是中間函數(shù)的調(diào)用者。絕大多數(shù)情況下,這個調(diào)用者可以和程序的主函數(shù)等同起來,但為了表示區(qū)別,我這里把它稱為 起始函數(shù) (如上面的代碼中注釋所示)。

之所以特意強(qiáng)調(diào)這個第三方,是因?yàn)槲以诰W(wǎng)上讀相關(guān)文章時(shí)得到一種印象,很多人把它簡單地理解為兩個個體之間的來回調(diào)用。譬如,很多中文網(wǎng)頁在解釋“回調(diào)”(callback)時(shí),都會提到這么一句話:“If you call me, I will call you back.”我沒有查到這句英文的出處。我個人揣測,很多人把起始函數(shù)和回調(diào)函數(shù)看作為一體,大概有兩個原因:第一,可能是“回調(diào)”這一名字的誤導(dǎo);第二,給中間函數(shù)傳入什么樣的回調(diào)函數(shù),是在起始函數(shù)里決定的。實(shí)際上,回調(diào)并不是“你我”兩方的互動,而是ABC的三方聯(lián)動。有了這個清楚的概念,在自己的代碼里實(shí)現(xiàn)回調(diào)時(shí)才不容易混淆出錯。

另外,回調(diào)實(shí)際上有兩種:阻塞式回調(diào)和延遲式回調(diào)。兩者的區(qū)別在于:阻塞式回調(diào)里,回調(diào)函數(shù)的調(diào)用一定發(fā)生在起始函數(shù)返回之前;而延遲式回調(diào)里,回調(diào)函數(shù)的調(diào)用有可能是在起始函數(shù)返回之后。這里不打算對這兩個概率做更深入的討論,之所以把它們提出來,也是為了說明強(qiáng)調(diào)起始函數(shù)的重要性。網(wǎng)上的很多文章,提到這兩個概念時(shí),只是籠統(tǒng)地說阻塞式回調(diào)發(fā)生在主調(diào)函數(shù)返回之前,卻沒有明確這個主調(diào)函數(shù)到底是起始函數(shù)還是中間函數(shù),不免讓人糊涂,所以這里特意說明一下。另外還請注意,本文中所舉的示例均為阻塞式回調(diào)。延遲式回調(diào)通常牽扯到多線程。

?

在Python中的一些使用示例:

實(shí)例一

            
              import
            
            
               random as rd


            
            
              #
            
            
               -----------被調(diào)用方----------------------------
            
            
              def
            
             newRN(fn):  
            
              #
            
            
               生成10個[0,1)之間小數(shù)
            
            
    ns =
            
               []
    
            
            
              for
            
             i 
            
              in
            
             range(10
            
              ):
        n 
            
            = round(rd.random(), 2
            
              )
        ns.append(n)

    
            
            
              #
            
            
               不用直接 return, 因?yàn)檎{(diào)用方 通知不接返回結(jié)果
            
            
              #
            
            
               改成回調(diào)函數(shù)方式
            
            
    fn(ns)  
            
              #
            
            
               調(diào)用是調(diào)用方函數(shù),這一操作稱之為回調(diào)
            
            
              #
            
            
               ----------------調(diào)用方------------------------
            
            
              #
            
            
               定義回調(diào)函數(shù)
            
            
              def
            
             abc(*
            
              args):
    
            
            
              #
            
            
               進(jìn)入到本函數(shù)內(nèi),意味著被調(diào)用方函數(shù)已執(zhí)行完
            
            
              print
            
            (
            
              '
            
            
              生成數(shù)據(jù)成功
            
            
              '
            
            
              )
    
            
            
              print
            
            
              (args)
newRN(abc)
            
          

輸出結(jié)果:

            
              生成數(shù)據(jù)成功
([
            
            0.27, 0.39, 0.81, 0.95, 0.78, 0.34, 0.89, 0.14, 0.19, 0.05],)
          

?

實(shí)例二

實(shí)例來源

我們來打個比方:

學(xué)校要進(jìn)行出入管制了,告訴門衛(wèi)發(fā)現(xiàn)寵物和車要上報(bào)(這個是回調(diào)函數(shù)注冊),然后管理人員根據(jù)門衛(wèi)的上報(bào)進(jìn)行處理(這個是回調(diào)函數(shù)的執(zhí)行)。

            
              import
            
            
               os,sys
Find
            
            =
            
              {
    
            
            
              '
            
            
              Type
            
            
              '
            
            :
            
              ''
            
            
              ,
    
            
            
              '
            
            
              Color
            
            
              '
            
            :
            
              ''
            
            
              ,
    
            
            
              '
            
            
              Size
            
            
              '
            
            :
            
              ''
            
            
              
}
            
            
              #
            
            
              定義匯報(bào)內(nèi)容
            
            
              def
            
             CallFun(cmd,Find):
            
              #
            
            
              回調(diào)函數(shù)的定義,在這里處理各種回調(diào)情況
            
            
              if
            
             cmd==
            
              '
            
            
              Type
            
            
              '
            
            
              :
        
            
            
              if
            
             Find[
            
              '
            
            
              Type
            
            
              '
            
            ]==
            
              '
            
            
              Dog
            
            
              '
            
            
              or
            
             Find[
            
              '
            
            
              Type
            
            
              '
            
            ]==
            
              '
            
            
              Cat
            
            
              '
            
            
              :
            
            
            
              print
            
            
              '
            
            
              A Pet:
            
            
              '
            
            
              else
            
            
              :
            
            
            
              print
            
            
              '
            
            
              A Transport:
            
            
              '
            
            
              elif
            
             cmd==
            
              '
            
            
              Print
            
            
              '
            
            
              :
        
            
            
              print
            
            
               Find
    
            
            
              else
            
            
              :
        
            
            
              print
            
            
              '
            
            
              error
            
            
              '
            
            
              def
            
             GiveInfo(i):
            
              #
            
            
              該段是填報(bào)信息,可忽略
            
            
    type0=[
            
              '
            
            
              Dog
            
            
              '
            
            ,
            
              '
            
            
              Cat
            
            
              '
            
            
              ]
    type1
            
            =[
            
              '
            
            
              Car
            
            
              '
            
            ,
            
              '
            
            
              Truck
            
            
              '
            
            
              ]
    color0
            
            =[
            
              '
            
            
              Black
            
            
              '
            
            ,
            
              '
            
            
              White
            
            
              '
            
            ,
            
              '
            
            
              Pink
            
            
              '
            
            
              ]
    size0
            
            =[
            
              '
            
            
              Big
            
            
              '
            
            ,
            
              '
            
            
              Middle
            
            
              '
            
            ,
            
              '
            
            
              Small
            
            
              '
            
            
              ]
    t0
            
            =i % 2
    
            
              if
            
              t0==
            
               0:
        Find[
            
            
              '
            
            
              Type
            
            
              '
            
            ] = type0[i%2
            
              ]
    
            
            
              else
            
            
              :
        Find[
            
            
              '
            
            
              Type
            
            
              '
            
            ] = type1[i%2
            
              ]
    Find[
            
            
              '
            
            
              Color
            
            
              '
            
            ] = color0[i%3
            
              ]
    Find[
            
            
              '
            
            
              Size
            
            
              '
            
            ] = size0[i%3
            
              ]

            
            
              def
            
             FindObj(num,cmd,CallBackFun):
            
              #
            
            
              發(fā)現(xiàn)目標(biāo),啟動回調(diào)函數(shù)
            
            
    GiveInfo(num)
            
              #
            
            
              門衛(wèi)填報(bào)信息
            
            
    CallBackFun(cmd,Find)
            
              #
            
            
              啟動回調(diào)函數(shù)
            
            
              if
            
            
              __name__
            
             == 
            
              '
            
            
              __main__
            
            
              '
            
            
              :
    cmds
            
            =[
            
              '
            
            
              Type
            
            
              '
            
            ,
            
              '
            
            
              Print
            
            
              '
            
            ,
            
              '
            
            
              Try
            
            
              '
            
            
              ]
    
            
            
              for
            
             i 
            
              in
            
             range(0,10):
            
              #
            
            
              定義十次上報(bào)
            
            
              print
            
            
              '
            
            
              ----------%d-------------
            
            
              '
            
            %
            
              i
        FindObj(i,cmds[i
            
            %3],CallFun)
            
              #
            
            
              這里注冊回調(diào)函數(shù)(就是告知門衛(wèi)的過程)
            
          
          回調(diào)利于模塊解耦。
        

?



?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 午夜67194| 欧美乱妇高清无乱码视频在线 | 精品久久亚洲一级α | 亚洲日韩中文字幕一区 | 欧美午夜毛片a级在线 | 日本精品久久久久中文字幕8 | 嘿咻嘿咻免费区在线观看吃奶 | 99热久久这里只有精品在 | 精品国产品香蕉在线观看75 | 天天摸夜夜 | 大香伊人久久 | 国产欧美另类第一页 | 人人97| 中文字幕在线观看亚洲日韩 | 午夜看一级特黄a大片黑 | 操碰在线视频 | 午夜亚洲精品久久久久久 | 手机在线看片不卡中文字幕 | 亚洲视频999 | 日韩欧美中文字幕一区 | 99精品久久精品一区二区 | 日韩一区二区三区四区 | 日日操狠狠干 | 久久精品亚洲 | 亚洲精品久久久久影院 | 一级欧美毛片成人免费视频 | 99热久久国产综合精品久久国产 | 亚洲成人伦理 | jazz欧美人免费xxxxxx | 漂亮女大学一级毛片 | 不卡一区 | 福利姬在线精品观看 | 素人259luxu在线观看暴露 | 国产91在线 | 日本 | 欧美一级毛片片免费孕妇 | 亚洲黄色在线观看视频 | 91精品国产爱久久久久 | 欧美成人久久久免费播放 | 天天操天天射天天舔 | 中文无码久久精品 | 久久频这里精品99香蕉久网址 |