如何在python中创建嵌套的生成器结构?

2024-09-27 23:22:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一个ImageSeries对象,在这个对象中,我希望以某种模式检索图像(对于xy中的每个值,以及z中的每个值),我调用将生成器附加到任务列表的方法,并通过两个for循环来运行生成器

但是,我的第二个任务在第一个任务的第一次迭代之后就耗尽了精力,这不是我想要的结果。我希望第二个任务运行第一个任务的每个迭代

我想知道是否有有效的方法来编程这样的模式

class ImageSeries:
    tasks = []

    def xy(self, position):
        print(position)
        yield "xy"

    def z(self, position):
        print(position)
        yield "z"

    def xy_scan(self, positions):
        self.tasks.append((self.xy(pos) for pos in positions))

    def z_scan(self, positions):
        self.tasks.append((self.z(pos) for pos in positions))

    def run(self):
        for i in self.tasks[0]:
            next(i)
            for j in self.tasks[1]:
                next(j)

    def __repr__(self):
        return str(self.tasks)
    

if __name__ == "__main__":
    s = ImageSeries()
    positions = [[0, 0], [100, 100], [1000, 1000]]
    s.xy_scan(positions)
    s.z_scan([0, 100, 1000, 10000])

电流输出:

[0, 0]
0
100
1000
10000
[100, 100]
[1000, 1000]

预期产出:

>>> s.run()
[0, 0]
0
100
1000
10000
[100, 100]
0
100
1000
10000
[1000, 1000]
0
100
1000
10000

Tags: 对象方法inposselfforscandef
2条回答

给你

class ImageSeries:
    def __init__(self):
        self._xy_tasks = None
        self._z_tasks = None

    def xy(self, position):
        print(position)
        yield "xy"

    def z(self, position):
        print(position)
        yield "z"

    def xy_scan(self, positions):
        self._xy_tasks = lambda: (self.xy(pos) for pos in positions)

    def z_scan(self, positions):
        self._z_tasks = lambda: (self.z(pos) for pos in positions)

    def run(self):
        for xy_generator in self._xy_tasks():
            next(xy_generator)
            for z_generator in self._z_tasks():
                next(z_generator)

    def __repr__(self):
        return str(self._xy_tasks()) + " " + str(self._z_tasks())


if __name__ == "__main__":
    s = ImageSeries()
    positions = [[0, 0], [100, 100], [1000, 1000]]
    s.xy_scan(positions)
    s.z_scan([0, 100, 1000, 10000])
    s.run()

做了一些事情:

  1. 调用run()
  2. self.tasks作为一个列表没有意义,因为每个单元格都有不同的含义,所以我将其分为两个单独的成员变量
  3. 主要的事情是确保在每次运行时都会再次创建生成器,因为它无法重置。我通过使用lambda实现了这一点,因此您可以调用每次都创建生成器的函数,而不是生成器本身。请注意self._xy_tasks()。这将调用创建生成器的函数

生成器不知道它们是嵌套的。发电机第一次耗尽后,就结束了。事实上,在这种情况下,您不需要生成器,因为当您迭代一个不希望存储在内存中的长列表时,它们会起作用。但在这里,你必须把所有重复的序列存储在内存中。只能在上层回路中使用生成器。但只有当它真的很长并且从某条溪流中获得时,它才有意义。如果它已经在内存中,那么实际上不需要生成器。你想要的一切都可以做得简单得多

xy_list = [[0, 0], [100, 100], [1000, 1000]]
z_list = [0, 100, 1000, 10000]
for xy in xy_list:
    print(xy)
    for z in z_list:
        print(z)

如果您需要它是一个类,只需使用xy_scanz_scan保存到self.xy_listself.z_list并使用相同的for循环inrun方法(只需将self.添加到xy_listz_list

相关问题 更多 >

    热门问题