同时生成器和上下文管理器
Generator and context manager at the same time
假设我有一些我想要的代码 运行:
with F() as o:
while True:
a = o.send(2)
print(a)
这意味着F
class应该return一个generator
也是context manager
,一般我想要一个上下文管理器作为生成器也是。
我试过这个:
class F:
def __enter__(self):
return self
def __exit__(self, *exc):
print('exit')
def __next__(self):
return 5
def __iter__(self):
return self
正如预期的那样,这将 return AttributeError: 'F' object has no attribute 'send'
,我通过添加以下内容来处理此错误:
def send(self, param):
self.__next__()
但我认为这不是一个好方法,我环顾四周发现 ,但他们没有按我的意愿使用 send
,我需要那个实例是发电机。
您可以使用 collections.abc
和子class 您的 class F
来自 Generator
(manual pages)。如果您实施 enter 和 exit,您的实例将成为生成器并具有上下文管理器支持:
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)
打印:
generator received 2
I received 42
...etc.
假设我有一些我想要的代码 运行:
with F() as o:
while True:
a = o.send(2)
print(a)
这意味着F
class应该return一个generator
也是context manager
,一般我想要一个上下文管理器作为生成器也是。
我试过这个:
class F:
def __enter__(self):
return self
def __exit__(self, *exc):
print('exit')
def __next__(self):
return 5
def __iter__(self):
return self
正如预期的那样,这将 return AttributeError: 'F' object has no attribute 'send'
,我通过添加以下内容来处理此错误:
def send(self, param):
self.__next__()
但我认为这不是一个好方法,我环顾四周发现 send
,我需要那个实例是发电机。
您可以使用 collections.abc
和子class 您的 class F
来自 Generator
(manual pages)。如果您实施 enter 和 exit,您的实例将成为生成器并具有上下文管理器支持:
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)
打印:
generator received 2
I received 42
...etc.