生成器和上下文管理器同时

时间:2018-07-16 05:51:33

标签: python python-3.x generator contextmanager

想象一下,我有一些要运行的代码:

with F() as o:
    while True:
        a = o.send(2)
        print(a)

这意味着F类应该返回一个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

如预期的那样,它将返回AttributeError: 'F' object has no attribute 'send',我通过添加以下内容来处理此错误:

def send(self, param):
    self.__next__()

但是我认为这不是一个好方法,我环顾四周并找到this,但是他们没有按我的意愿使用send,我需要该实例作为生成器。

1 个答案:

答案 0 :(得分:1)

您可以使用collections.abc并从Fmanual pages)继承类Generator的类。如果您实现 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.