【发布时间】:2014-02-16 06:32:44
【问题描述】:
有没有办法在生成器的定义中获取对返回的生成器对象的引用?这类似于传递给迭代器的__next__ 方法内部的方法的self 参数。在浏览了 Python 的文档后,我没有发现任何类似的东西。
当我在探索以下论文中的多少想法时,我提出了这个问题,我可以使用生成器作为协程在 Python 中实现多少。论文:http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.79
我能做的最接近的方法是使用装饰器,它基于 David Beazley 的 coroutine 装饰器,但感觉有点像 hack。
from functools import wraps
def coroutine(func):
@wraps(func)
def decorated(*args, **kwargs):
f = func(*args, **kwargs)
next(f)
f.send(f)
return f
return decorated
@coroutine
def A():
self = yield
# do stuff...
编辑:基于下面的答案,以下类可用作装饰器,以使生成器接收对 self 的引用作为其第一个参数。它还有一个额外的好处是,任何用它装饰的生成器都将具有 coroutine 类型。
class coroutine(object):
"""Decorator class for coroutines with a self parameter."""
def __new__(cls, func):
@wraps(func)
def decorated(*args, **kwargs):
o = object.__new__(cls)
o.__init__(func, args, kwargs)
return o
return decorated
def __init__(self, generator, args, kw):
self.generator = generator(self, *args, **kw)
next(self.generator)
def __iter__(self):
return self
def __next__(self):
return next(self.generator)
next = __next__
def send(self, value):
return self.generator.send(value)
# Usage:
@coroutine
def A(self):
while True:
message = yield
print self is message
a = A()
b = A()
a.send(a) # outputs True
a.send(b) # outputs False
【问题讨论】:
-
我已经简要浏览了大约三分之一的论文,我没有看到任何你希望协程引用自身的内容。不过,看起来您希望协程能够在任何给定索引处触发协程。这是准确的,还是我应该回去实际阅读论文而不是略读?
-
如果你确实想让协程引用自身,你会用它做什么?协程会将自己作为回调传递给代码的其他部分吗?
-
你能放一些用例吗,其实我不清楚你在做什么。
-
有趣的问题 (+1)。鉴于要求是多么深奥,您的解决方案并没有让我觉得有一半是坏的。也就是说,看看有人能不能想出一些更整洁的东西确实很有趣……
-
了解您的确切用例也会很有趣。