我有许多Python生成器,我想将它们组合成一个新的生成器。我可以很容易地通过一个手写的生成器使用一堆
yield
声明。
另一方面,
itertools
模块是为类似这样的事情而设计的,在我看来,创建生成器的蟒蛇式方法似乎是将它的各种迭代器插入到一起。
迭代工具
模块。
然而,在目前的问题中,它很快变得相当复杂(发电机需要保持某种状态,例如,第一个或之后的项目是否正在处理中),第i个输出进一步取决于第i个输入项目的条件,并且在将各种输入列表加入通用电气之前,必须对它们进行不同的处理。系留列表
由于标准迭代器的组合可以解决我的问题——由于源代码的一维特性——几乎不可理解,我想知道使用标准是否有任何好处
迭代工具
生成器与手写生成器函数(在基本和更高级的情况下)。实际上,我认为在90%的情况下,手写版本更容易阅读——可能是因为与链接迭代器的功能风格相比,手写版本更具有命令式风格。
编辑
为了说明我的问题,这里有一个(玩具)例子:让
a
和
b
是两个相同长度的iterable(输入数据)。项目
一
包含整数,项
乙
是ITerables本身,其单个项是字符串。输出应与以下发电机功能的输出相对应:
from itertools import *
def generator(a, b):
first = True
for i, s in izip(a, b):
if first:
yield "First line"
first = False
else:
yield "Some later line"
if i == 0:
yield "The parameter vanishes."
else:
yield "The parameter is:"
yield i
yield "The strings are:"
comma = False
for t in s:
if comma:
yield ','
else:
comma = True
yield t
如果我使用生成器表达式和
迭代工具
模块,我最终得到如下的结果:
from itertools import *
def generator2(a, b):
return (z for i, s, c in izip(a, b, count())
for y in (("First line" if c == 0 else "Some later line",),
("The parameter vanishes.",) if i == 0
else ("The parameter is:", i),
("The strings are:",),
islice((x for t in s for x in (',', t)), 1, None))
for z in y)
例子
>>> a = (1, 0, 2), ("ab", "cd", "ef")
>>> print([x for x in generator(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']
>>> print([x for x in generator2(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']
这可能比我的第一个解决方案更优雅,但看起来像是一次写一次不理解以后的代码。我想知道这种编写生成器的方法是否有足够的优势,人们应该这样做。
P.S.:我想我对函数解决方案的部分问题是,为了尽量减少python中的关键字数量,一些关键字(如“for”、“if”和“else”)已被回收用于表达式中,以便它们在表达式中的位置变得习惯(生成器表达式中的顺序
z for x in a for y in x for z in y
至少对我来说,看起来不像经典的那种
for
循环:
for x in a: for y in x: for z in y: yield z
)