【问题标题】:Generator and context manager at the same time同时生成生成器和上下文管理器
【发布时间】:2018-12-23 14:48:09
【问题描述】:

假设我有一些我希望它运行的代码:

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,我需要该实例作为生成器。

【问题讨论】:

    标签: python python-3.x generator contextmanager


    【解决方案1】:

    您可以使用collections.abc 并将您的类FGenerator (manual pages) 子类化。如果您实现 enterexit,您的实例将成为生成器并且还具有上下文管理器支持:

    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.
    

    【讨论】:

    • 这肯定比我的解决方案好,谢谢,现在唯一的问题是:o 不能是生成器的实例吗?因为我不想在课堂上实现send
    • @mehrdad-pedramfar collections.abc.Generator 将为您实现close, __iter__, __next__(如果您提供sendthrow 方法)。如果你不是 Generator 的子类,你需要自己实现所有这些方法。
    猜你喜欢
    • 2021-09-19
    • 2011-07-13
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多