Chinaunix首页 | 论坛 | 博客
  • 博客访问: 351669
  • 博文数量: 82
  • 博客积分: 3353
  • 博客等级: 中校
  • 技术积分: 742
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-20 19:13
文章分类

全部博文(82)

文章存档

2015年(1)

2014年(1)

2013年(1)

2012年(12)

2011年(3)

2010年(25)

2009年(37)

2008年(2)

我的朋友

分类: Python/Ruby

2010-04-08 17:28:53

Defer()的方法:addCallback()callback()

 

 之前对addCallback()callback(),如何使用以及它们的工作原理一直弄不明白,只知道是回调机制,经过学习,总结如下:

Twisted中,reactordefer是核心。Reactor是为程序运行建立全局循环;defer则是实现了回调机制。

         Defer()类中,有一个变量self.called,这个很关键,决定着addCallback(func,*args,**kw)中能否执行所传入的函数func,self.called是在callback()被设置的self.called=True。所以,要执行func(),就必须有一个callback(),而且只能有一个,测试过,有两个就报错。下面这段代码是报错的原因(self.called已经被赋值,在下面还可以从另一个角度看明白):

if self.called:

            if self.debug:

                if self._debugInfo is None:

                    self._debugInfo = DebugInfo()

                extra = "\n" + self._debugInfo._getDebugTracebacks()

                raise AlreadyCalledError(extra)

            raise AlreadyCalledError

 

Defer()类中,有一个列表self.callbacks = [],保存的是addCallback()传入的函数和参数的,每调用一次,在self.callbacks中就多一项,可以保存很多组,可以多次调用addCallback()。经过多次调用,那各次调用的函数func()(各次不同或者相同)是否有联系呢?可以有,也可以没有。Func()执行时,所传入的参数不仅仅是addCallback()中的args,kw。实际的执行过程是这样的:

self.result = callback(self.result, *args, **kw)    

                            #这里的callback()就是上面的func()

 

self.resultDefer()类的变量,最开始的值是由callback()传入的。通过循环,提取self.callbacks中的项,调用self.result = callback(self.result, *args, **kw),上一次的结果self.result作为下一项的第一个参数传入下一个函数,所以只需要第一次调用时需要外界传入参数。当然,没有参数也是可以的,但是callback()必须调用一次,因为self.called需要设置。这里也可以看出为什么callback()只能调用一次,因为参数只需要传入最初的一个就够了(这些都是个人猜想,非官方信息)。(如果想让callback()可以多次调用,也是可以的,修改defer.py文件中的_startRunCallbacks()。玩笑,这样做肯定有原因的)

 

回调机制,是让一件事自己去做,做好了之后再来通知我。

 

假设我们有三个函数main(),funA(),funB().main()是主程序,有很多事要做,因为功能需要,funA()的运行必须是在funB()运行完之后。如果采用普通返回值的方式,是比较费时,而且效率不高的。我们如何让funB()运行完之后自动去执行funA()呢?回调机制可以解决。我们只要在funB()所有语句之后生成defer,然后调用defer.callback(),最后返回这个defer。而在main()函数中,在执行了d = funB()语句后,添加d.addCallback(funA,),就是把funA()添加到callbaks = []列表中,那样就会在funB()执行完后自动被执行。如果希望在funB()执行之后再执行多个动作,只要将那些动作(函数)添加到callbacks =[] 列表中即可,会按添加顺序执行。

如果在执行callbacks = []列表里的项出错时,那会发生什么呢?会转而执行addErrback()所添加的。

Each callback will have its result passed as the first

argument to the next; this way, the callbacks act as a

'processing chain'. Also, if the success-callback returns a L{Failure}

or raises an L{Exception}, processing will continue on the *error*-

callback chain.

上面这段是callback()函数的说明。

阅读(1965) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~