回调函数在C语言中经常使用,简单来说就是将回调函数的指针地址作为参数传递一个函数,而那个函数在需要用到的时候利用传递的地址回调函数。这时就可以利用这个机会在回调函数中处理或者完成操作。
比如下面的C语言代码。printWelcome的地址传递给(*print)(int).在callback中就可以调用
void printWelcome(intlen)
{
printf("welcome -- %d/n",len);
}
void callback(inttimes, void (* print_info)(int))
{
inti;
for(i = 0; i < times; ++i)
{
Print_info(i);
}
void main(void)
{
callback(10,printWelcome);
}
我们通俗点来说,回调函数就好比你去商店买了东西,但是没货,这个时候你留了电话号码给店员,等到有货的时候店员打电话给你让你取取货。你的电话号码就相当于回调函数。
来看下python中的回调函数如何用:
def apply_async(func,args,callback):
result=func(*args)
callback(result)
def print_result(result):
print result
def add(x,y):
return x+y
apply_async(add,(2,3),callback=print_result)
在apply_async中设置callback为print_result.当add加法运行完以后,则可以调用print_result来打印。
有人会问,这和写中间函数有什么区别呢:代码改成如下不也是一样,在appy_async中调用print_result不是一样的么
def apply_async(func,args):
result=func(*args)
print_result(result)
def print_result(result):
print result
def add(x,y):
return x+y
if __name__=='__main__':
apply_async(add,(2,3))
确实这样写也是一样的效果,那么回调函数有什么好处呢?如果更新下我们的需求,在apply_async中我们还想打印出2个参数相减的结果。代码可以改成如下
def apply_async(func,func1,args):
result=func(*args)
print_result(result)
result1=func1(*args)
print_result(result1)
def print_result(result):
print result
def delete(x,y):
return x-y
def add(x,y):
return x+y
if __name__=='__main__':
apply_async(add,delete,(2,3))
但是如果需求继续增加,我们还想打印乘法,除法,幂运算等各种运算结果呢。这个时候在apply_async中不是得传递各种函数参数。参数越写愈多,也越来越不好看。这个时候回调函数的优势就体现出来了。
def apply_async(func,args,callback):
result=func(*args)
callback(result)
def print_result(result):
print result
def delete(x,y):
return x-y
def add(x,y):
return x+y
if __name__=='__main__':
apply_async(add,(2,3),callback=print_result)
apply_async(delete,(2,3),callback=print_result)
看到没,我只需要给apply_async的第一个参数传递不同的处理函数,我就可以得到不同的结果。而回调函数都是固定的。这就相当于将公共部分用回调函数来处理。而apply_async通过参数的传递得到了不同的结果。
在上面的回调函数中,回调函数只能处理传入的参数,无法访问其他变量。
为了让回调函数访问外部信息,有两种方法:1 使用一个绑定方法来代替一个简单函数
class ResultHandler:
def __init__(self):
self.sequence=0
def handler(self,result):
self.sequence+=1
print self.sequence,result
r=ResultHandler()
apply_async(add,(2,3),r.handler)
apply_async(add,(4,4),r.handler)
在这里首先创建类ResultHandler的实例,然后用handler来作为回调函数,这个时候就可以同步访问sequence这个变量
第二种方法就是使用闭包。
def make_handler():
sequence=0
def handler(result):
nonlocal sequence
sequence+=1
print sequence,result
return handler
hanlder=make_handler()
apply_async(add,(2,3),callback=hanlder)
注意nonlocal是在Python3.0才使用的。在2.x是没有这个关键字的。因此在2.x中要么使用全局变量,要么使用列表或者字典。如果使用变量,会报错。因此系统不知道这个变量是在哪引用的。
def make_handler():
sequence=[1]
def handler(result):
sequence[0]=2
print sequence,result
return handler