Есть ли способ получить ссылку на возвращаемый объект генератора внутри определения генератора? Это было бы похоже на аргумент self
, переданный методу внутри метода __next__
итератора. После просмотра документации Python я не нашел ничего похожего на нее.
Этот вопрос возник, когда я изучал, как много из следующих бумажных идей я могу реализовать в Python, используя генераторы в виде сопрограмм. Бумага: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.79
Ближайшим, что я мог сделать, было следующее, используя декоратор, который строится на декораторе Дэвида Безли coroutine
, но он чувствует себя немного взломанным.
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...
EDIT: Следующий класс, основанный на ответе ниже, может использоваться в качестве декоратора, чтобы генератор получал ссылку на 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