问题
Imagine I have some code that I want it to run:
with F() as o:
while True:
a = o.send(2)
print(a)
It means that the F
class should return an generator
and also it is context manager
, generally I want a context manager to be generator too.
I tried this:
class F:
def __enter__(self):
return self
def __exit__(self, *exc):
print('exit')
def __next__(self):
return 5
def __iter__(self):
return self
As expected this will return AttributeError: 'F' object has no attribute 'send'
, I handled this error by adding:
def send(self, param):
self.__next__()
but I think it is not a good way to do this, I look around and find this, but they are not using send
as I want, I need that instance to be a generator.
回答1:
You can use collections.abc
and subclass your class F
from Generator
(manual pages). If you implement enter and exit, your instance will be generator and have context manager support as well:
from collections.abc import Generator
class F(Generator):
def __init__(self):
self.__my_generator = self._my_generator()
next(self.__my_generator) # prime the generator
def _my_generator(self):
while True:
v = yield 42
print('generator received ', v)
# context manager interace:
def __enter__(self):
return self
def __exit__(self, *exc):
print('exit')
# Generator interface:
def send(self, value):
return self.__my_generator.send(value)
def throw(self, typ, value=None, traceback=None):
return self.__my_generator.throw(typ, value, traceback)
with F() as o:
while True:
a = o.send(2)
print('I received ', a)
Prints:
generator received 2
I received 42
...etc.
来源:https://stackoverflow.com/questions/51355310/generator-and-context-manager-at-the-same-time