是否存在生成器装饰器?

时间:2011-09-07 19:35:15

标签: python twisted

我在使用Twisted时只是跟踪了一个随机错误:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/twisted/spread/pb.py", line 826, in proto_message
    self._recvMessage(self.localObjectForID, requestID, objectID, message, answerRequired, netArgs, netKw)
  File "/usr/lib/python2.7/dist-packages/twisted/spread/pb.py", line 840, in _recvMessage
    netResult = object.remoteMessageReceived(self, message, netArgs, netKw)
  File "/usr/lib/python2.7/dist-packages/twisted/spread/flavors.py", line 114, in remoteMessageReceived
    state = method(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1141, in unwindGenerator
    return _inlineCallbacks(None, f(*args, **kwargs), Deferred())
--- <exception caught here> ---
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1020, in _inlineCallbacks
    result = g.send(result)
exceptions.AttributeError: 'NoneType' object has no attribute 'send'

这是由以下原因引起的:

@defer.inlineCallbacks
def myfunc():
    # Function implementation with no yield statement.

myfunc被调用时,我会打印出之前的回溯,但函数内的所有内容都能正常工作。这是因为它在调用时返回None而不是生成器,defer.inlineCallbacks期望返回它。有没有办法将函数声明为生成器而不在函数体中放置yield语句?比如发电机装饰器?

3 个答案:

答案 0 :(得分:6)

正如其他人所说,这可能毫无意义。但为了完整性并回答这个问题:

,您必须使用yield使其成为生成器,当然,如果您创建一个生成器的装饰器(通过包含yield关键字)本身,但实际上并没有产生任何东西,只是调用装饰函数。这样的yield可以无法访问且毫无意义(if False: yield),但它必须存在。由于这不是常见的需求,因此没有像预先构建的那样,至少我没有意识到。最简单的方法是将它添加到你的函数中,编写你自己的装饰器在一些情况下是不值得的,如果你经常需要它,没有你的设计可能有问题,你应该修改它。

答案 1 :(得分:1)

如果你真的需要它,那就做一个。

#like this
def generator(callable):
    def asgenerator(*args, **kwargs):
        while True:
            yield callable(*args, **kwargs)
    return asgenerator

虽然如其他人所说,这可能隐藏了一个设计问题。

答案 2 :(得分:1)

看起来你碰到了Ticket 2501。这已在主干中修复,您遇到的错误将来会更加清晰。