Python Twisted中奇怪的回调执行顺序?

Python Twisted中奇怪的回调执行顺序?,python,twisted,Python,Twisted,考虑以下代码: from twisted.internet.defer import Deferred d1 = Deferred() d2 = Deferred() def f1(result): print 'f1', def f2(result): print 'f2', def f3(result): print 'f3', def fd(result): return d2 d1.addCallback(f1) d1.addCallback(

考虑以下代码:

from twisted.internet.defer import Deferred

d1 = Deferred()
d2 = Deferred()

def f1(result):
    print 'f1',

def f2(result):
    print 'f2',

def f3(result):
    print 'f3',

def fd(result):
    return d2

d1.addCallback(f1)
d1.addCallback(fd)
d1.addCallback(f3)

#/BLOCK====
d2.addCallback(f2)
d1.callback(None)
#=======BLOCK/

d2.callback(None)
这输出了我所期望的:

f1 f2 f3
但是,当我将块中语句的顺序交换为

#/BLOCK====
d1.callback(None)
d2.addCallback(f2)
#=======BLOCK/
i、 e.在将回调添加到d2之前触发d1,我得到:

f1 f3 f2
我不明白为什么延迟触发的时间会影响回调执行顺序。

这是Twisted的问题还是在某种程度上有意义;dr-当您从回调(
fd
)返回一个延迟(
d2
)时,它将被插入到名为
fd
的任何延迟(
d1
)的回调链中。这是通过将
d1
的回调链的延续添加为
d2
上的回调来实现的,因此,如果在触发
d1
后将回调添加到
d2
,它将在
d1
的延续后被锁定


我认为您忽略了延迟本身并不是异步的这一事实,它们只是异步代码中链接回调和错误处理程序的一种更结构化的方式。回调不会在以后某个未指定的时间调用,而是在触发延迟时调用。如果您希望稍后进行此操作,则需要将调用与
反应器集成

因此,也许这让这个问题的答案更加明显:

我不明白为什么延迟触发的时间会影响回调执行顺序

如果在触发延迟后更改回调,则会发生这种情况

对代码的解释 在第一个示例中:
  • d1.回调(无)
    导致触发
    d1
  • 调用
    f1
    (打印“f1”)
  • 调用
    fd
    (返回
    d2
  • 现在事情停止了,因为
    d2
    已经在
    f1
    f3
    之间为
    d1
    ,但还没有被触发。然后

  • d2。回调(无)
    导致
    d2
    被激发
  • f2
    被调用(打印“f2”)
  • d1
    的回调链恢复;因此调用了
    f3
    (打印“f3”)
  • 在第二个例子中
  • d1.回调(无)
    导致触发
    d1
  • 调用
    f1
    (打印“f1”)
  • 调用
    fd
    (返回
    d2
  • 此处,
    d2
    再次插入回调链。完成此操作的方法是作为对
    d2
    的回调。因此,即使您明确地将
    f2
    添加为
    d2
    上的回调,它也是在
    d1
    的回调链的延续之后添加的。因此

  • d2.回调(无)
    导致
    d2
    被触发;这将导致
    d1
    的回调链继续,从
  • f3
    被调用(打印“f3”)
  • d2
    在其链中的下一个回调是
    f2
    ,因此
  • f2
    被调用(打印“f2”)

  • 这在d2火灾和f3被调用后是有意义的。如果没有虫洞技术,就无法在f3之前调用f2。然而,在我的例子中,d2还没有开火。所以f3也还没有被调用。你仍然可以得到正确的订单@抱歉,我删除了我的详细解释,因为它们是不正确的(因此非常混乱)!我将不得不多考虑一下延迟被同步调用会发生什么。@SlashV-好的,算了吧!如果语言混乱,请告诉我。谢谢你的解释。我现在明白了为什么它是这样工作的。不过,我仍然不知道为什么有必要这样做。我将不得不研究延续的问题。@SlashV-我不是一个扭曲的开发人员,但这似乎是一种拥有可暂停/可恢复回调链的明智方法,该回调链自动包含返回的延迟。请记住,您的代码(同步、交错的回调添加和触发)并不是一个真正的预期用例,这里的一致性无论如何都是不明确的。所以“做对”可能不是设计的首要任务。