我希望能够“发送”和“接收”数据 从一个类似于你如何使用发生器这样做的对象。
首先,一个解释。能够做到这一点会很高兴,因为我有一个我称之为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>
但是,这不允许所需的行为,即保留在逻辑序列中并将控制权传递回调用对象的next
或send
方法的代码。
现在,这些都是非法的:
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)
这一切都很好,但它仍然只是一种创建单独的生成器的方法,具有更好的语法。
有没有办法让真实的,实际的生成器行为在用户定义的对象中工作?