2

ツイストでdefer関数を使用すると、パラメーターが混乱します。

関数のパラメーターがINT-VALUEであるか、listとdict以外の他の基本的な型であるかどうかを検討しますが、参照ではなく値を渡す必要があります。

from twisted.internet import defer, reactor

def deferFunc(x):
    print "11111 %d" % x
    d = defer.Deferred()
    reactor.callLater(1, d.callback, x)
    return d

@defer.inlineCallbacks
def inlineDeferFunc(x):
    print "11111 %d" % x
    d = defer.Deferred()
    reactor.callLater(1, d.callback, x)
    result = yield d
    defer.returnValue(result)

def loop():
    x = [1,2,3,4]
    d = defer.succeed(0)
    for i in x:
        d.addCallback(lambda _ : inlineDeferFunc(i))

if __name__ == '__main__':
    loop()

    try:
        reactor.run()
    except:
        reactor.stop()

結果は:

11111 1
11111 4
11111 4
11111 4

その結果、私は混乱しました。

1,2,3,4のような正しい出力を取得するにはどうすればよいですか?

4

1 に答える 1

3

1,2,3,4のような正しい出力を取得するにはどうすればよいですか?

このような:

def loop():
    x = [1,2,3,4]
    d = defer.succeed(0)
    for i in x:
        d.addCallback(lambda _, i = i : inlineDeferFunc(i))



11111 1
11111 2
11111 3
11111 4

関数定義の値をコピーしていることに注意してくださいi = i
問題は、パフォーマンス上の理由から、変数が定義中にコピーされるとは思わないが、親環境がループによって更新され続けるlambdaため、変数にアクセスするために親環境を取得することでした。ifor

これが簡単なテストです。

>>> def test_closures():
...     i = 2
...     def test():
...         return i
...     i = 3
...     return test
... 
>>> test_closures()()
3
于 2012-07-15T02:57:49.303 に答える