我最近在学习Twisted,现在我重新阅读了Deferred的一些基本文档,这是来自以下代码的示例代码:http://twistedmatrix.com/documents/12.3.0/core/howto/defer.html

注释掉第二个g = Getter()怎么样?
会重新输入问题吗?关于如何避免此类问题,您是否有一些好主意?

from twisted.internet import reactor, defer

class Getter:
    def gotResults(self, x):
        """
        The Deferred mechanism provides a mechanism to signal error
        conditions.  In this case, odd numbers are bad.

        This function demonstrates a more complex way of starting
        the callback chain by checking for expected results and
        choosing whether to fire the callback or errback chain
        """
        if self.d is None:
            print "Nowhere to put results"
            return

        d = self.d
        self.d = None
        if x % 2 == 0:
            d.callback(x*3)
        else:
            d.errback(ValueError("You used an odd number!"))

    def _toHTML(self, r):
        """
        This function converts r to HTML.

        It is added to the callback chain by getDummyData in
        order to demonstrate how a callback passes its own result
        to the next callback
        """
        return "Result: %s" % r

    def getDummyData(self, x):
        """
        The Deferred mechanism allows for chained callbacks.
        In this example, the output of gotResults is first
        passed through _toHTML on its way to printData.

        Again this function is a dummy, simulating a delayed result
        using callLater, rather than using a real asynchronous
        setup.
        """
        self.d = defer.Deferred()
        # simulate a delayed result by asking the reactor to schedule
        # gotResults in 2 seconds time
        reactor.callLater(2, self.gotResults, x)
        self.d.addCallback(self._toHTML)
        return self.d

def printData(d):
    print d

def printError(failure):
    import sys
    sys.stderr.write(str(failure))

# this series of callbacks and errbacks will print an error message
g = Getter()
d = g.getDummyData(3)
d.addCallback(printData)
d.addErrback(printError)

# this series of callbacks and errbacks will print "Result: 12"
#g = Getter() #<= What about commenting this line out?
d = g.getDummyData(4)
d.addCallback(printData)
d.addErrback(printError)

reactor.callLater(4, reactor.stop)
reactor.run()

最佳答案

是的,如果您对第二个g = Getter()进行注释,则会遇到问题。相同的Deferred将触发两次,因为您将Deferred存储在Getter对象中。特别是,对getDummyData的第二次调用将覆盖第一个Deferred

你不应该这样做。总的来说,我认为保留Deferred对象不是一个好主意,因为它们只能触发一次,而且像您一样容易遇到问题。

您应该这样做:

def getDummyData(self, x):
    ...
    d = defer.Deferred()
    # simulate a delayed result by asking the reactor to schedule
    # gotResults in 2 seconds time
    reactor.callLater(2, self.gotResults, x, d)
    d.addCallback(self._toHTML)
    return d


和:

def gotResults(self, x, d):
    """
    The Deferred mechanism provides a mechanism to signal error
    conditions.  In this case, odd numbers are bad.

    This function demonstrates a more complex way of starting
    the callback chain by checking for expected results and
    choosing whether to fire the callback or errback chain
    """
    if d is None:
        print "Nowhere to put results"
        return

    if x % 2 == 0:
        d.callback(x*3)
    else:
        d.errback(ValueError("You used an odd number!"))


请注意,在这种情况下,Getter没有状态,这很好,并且您不需要类!

我的观点是,应使用Deferred使函数的调用者可以在结果可用时对结果执行某些操作。他们不应该被用于任何幻想。所以,我总是

def func():
    d = defer.Deferred()
    ...
    return d


如果呼叫者出于某种原因必须坚持使用Deferred,则可以,但是我可以多次自由呼叫func,而不必担心隐藏状态。

关于python - 以下扭曲代码是否会重新输入问题?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19528527/

10-12 23:14