用户定义的类生成器对象,您可以从

时间:2017-08-02 21:06:54

标签: python generator

我希望能够“发送”和“接收”数据 从一个类似于你如何使用发生器这样做的对象。

为什么

首先,一个解释。能够做到这一点会很高兴,因为我有一个我称之为Obj的对象类型,其实例必须逐步创建和提取。我已经将增量对象迭代序列实现为一系列生成器;我之所以这样做是因为该对象是一种非常“选择你自己的冒险”类型的东西,根据前面的内容,不同的路径分叉,并且每个逻辑步骤可能很复杂,并且可能在将来发生变化。逻辑的一部分看起来像这样(它要复杂得多):

# objiter module

def PartX(obj):
    # obj does not yet have attr8
    yield 'PartX'
    # obj now has attr8
    if obj.attr1 == 1:
        yield from PartY(obj)
    if obj.attr1 == 2:
        yield from PartZ(obj)

def PartY(obj):
    yield 'PartY'

def PartZ(obj):
    # obj does not yet have Z
    yield from PartZ1
    # obj now has Z
    if hasattr(obj.Z, 'zattr1'):
        yield from PartZ1
    if hasattr(obj.Z, 'zattr2'):
        yield from PartZ2

对象迭代序列可以通过start_iter方法启动。来自增量逻辑的每个产生的字符串与来自输入文件的行配对。

有一个Builder类,它是一个描述符;它接收数据并实际对Obj实例进行增量更改。数据由每一行(来自输入文件)和标签(来自增量逻辑发生器)使用get_data方法创建。

这是一个基本的表示:

from .objiter import PartA
from .parse import parse_line


class Obj():
    # builder is a descriptor and context manager, used below  in load_file
    builder = Builder()
    @staticmethod
    def get_data(line, label):
        '''Makes data out of a line, label pair.'''
        parse_line(line, label)
    def _start_iter(self):
        '''Kick off object incremental logic.'''
        # begin incremental logic
        yield from PartA(self)
    @classmethod
    def load_file(cls, file_lines):
        '''Construct an instance from an input file.'''
        self = Obj() # an "empty" object
        iter_logic = self._start_iter()
        # start object creation
        with self.builder as obj_builder:
            for line, label in zip(lines, iter_logic):
                data = obj.get_data(line, label)
                obj_builder.send(data, label)
        # object creation complete

我想做什么

能够简单地直接将数据注入并从对象实例接收数据而不是使用builder描述符实例,这将是一件好事。我首选的解决方案是允许我编写这样的代码(参见最后几行):

            for line, label in zip(lines, iter_logic):
                data = obj.get_data(line, label)
                self.send(data, label)
                more_data = next(self)

我可以做以下事情:

    def send(self, data, label):
        self.handle_data(data, label)
    def __next__(self):
        return <some_data>

但是,这不允许所需的行为,即保留在逻辑序列中并将控制权传递回调用对象的nextsend方法的代码。

我尝试了什么

现在,这些都是非法的:

class C(FunctionType): pass
class C(GeneratorType): pass

所以你不能制造“类似发电机”的物体。我考虑过一个返回生成器的上下文管理器,如下所示:

    def generate_me(self):
        '''The logic of handling commands and data.'''
        while True:
            command = yield
            <handle the command by sending/receiving data>
    def __enter__(self):
        self.generator = self.generate_me()
        return self.generator
    def __exit__(self, owner, value, tb):
        self.generator.close()
        del self.generator

然后我可以做:

obj = Obj()
with obj as obj_gen:
    obj_gen.send(data)
    data = next(obj_gen)

这一切都很好,但它仍然只是一种创建单独的生成器的方法,具有更好的语法。

有没有办法让真实的,实际的生成器行为在用户定义的对象中工作?

0 个答案:

没有答案