如何在 python 中创建嵌套的生成器结构?
How to create nested generator structures in 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
给你
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()
做了一些事情:
- 叫
run()
- self.tasks 作为列表没有任何意义,因为每个单元格都有不同的含义,所以我将它分成两个单独的成员变量。
- 主要是确保在每个 运行 上再次创建生成器,因为它无法重置。我通过使用 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)
如果你需要它是class,只需使用xy_scan
,z_scan
保存到self.xy_list
,self.z_list
并使用相同的for
在 run
方法中循环(只需将 self.
添加到 xy_list
和 z_list
)
我正在尝试创建一个 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
给你
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()
做了一些事情:
- 叫
run()
- self.tasks 作为列表没有任何意义,因为每个单元格都有不同的含义,所以我将它分成两个单独的成员变量。
- 主要是确保在每个 运行 上再次创建生成器,因为它无法重置。我通过使用 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)
如果你需要它是class,只需使用xy_scan
,z_scan
保存到self.xy_list
,self.z_list
并使用相同的for
在 run
方法中循环(只需将 self.
添加到 xy_list
和 z_list
)