回调函数的浅显理解

什么是回调函数

        回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。如

def a(i):

    print("this is a start")

    print(i)

    print("this is a stop")

def b(func):

    print("this is b start")

    for i in range(2):

        func(i)

    print("this is b stop")

b(a)

        函数a就被称为回调函数,但回调函数不是由该函数的实现方直接使用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

回调函数作用

        回调函数的常见应用场景是应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。回调函数通常和应用处于同一抽象层(因为传入什么样的回调函数是在应用级别决定的)。而回调就成了一个高层调用底层,底层再回过头来调用高层的过程。如在Urllib模块中的urlretrieve方法的原型为

                                            urlretrieve(url,filename=None, reporthook=None, data=None)

      它可以接收一个回调函数指针赋给reporthook参数,而我们可以在回调函数中编写下载进度的代码,如

def callbackfunc(blocknum, blocksize,totalsize):

   '''回调函数

   @blocknum:已经下载的数据块

   @blocksize:数据块的大小

   @totalsize:远程文件的大小

   '''

   percent = 100.0 * blocknum * blocksize / totalsize                            

   if percent > 100:

        percent = 100

   print "%.2f%%"% percent                           #打印进度

url ='http://download.redis.io/redis-stable.tar.gz'

newfilename = 'test/redis.tar.gz'

urllib.urlretrieve(url, newfilename,callbackfunc)

      上述回调的作用可以看做一种通知机制,库函数每下载并写入1blocksize大小的内容后,通知callback函数,在callback中打印下载进度,但库函数的实现者对我们自定义的回调函数一无所知。就需有一个特定原型的函数指针,用这个指针来进行回调,来通知我们的程序事件已经发生。库函数调用了回调函数,但我们的回调函数本质上使用的还是库函数的服务。在库函数代码中,我们可以看到这样一段代码

bs = 1024*8

size = -1

read = 0

blocknum = 0

if "content-length" inheaders:

   size = int(headers["Content-Length"])

if reporthook:

   reporthook(blocknum, bs, size)

while 1:

   block = fp.read(bs)

   if block == "":

        break

   read += len(block)

   tfp.write(block)

   blocknum += 1

   if reporthook:

        reporthook(blocknum, bs, size)

       乍看起来,回调似乎只是函数间的调用,但仔细一琢磨,可以发现两者之间的一个关键的不同:在回调中,我们利用某种方式,把回调函数像参数一样传入库函数。可以这么理解,在传入一个回调函数之前,库函数是不完整的。换句话说,程序可以在运行时,通过登记不同的回调函数,来决定、改变库函数的行为。这就比简单的函数调用要灵活太多了。



我只是知识的搬运工,如有侵权,请留言,立即删除。

你可能感兴趣的:(回调函数的浅显理解)