【发布时间】:2010-12-17 06:00:06
【问题描述】:
更新:我一直想要的是greenlets。
注意:当人们回答并迫使我“提高赌注”时,这个问题发生了一些变化,因为我的琐碎示例进行了琐碎的简化;根据 Alex 的建议,我不会在此处继续对其进行变异,而是在头脑更清晰时提出这个问题。
Python 生成器很漂亮,但我怎样才能轻松地将其分解为模块(结构化编程)?我实际上想要PEP 380,或者至少在语法负担上相当的东西,但在现有的Python(例如2.6)中
作为一个(诚然愚蠢的)例子,采取以下方式:
def sillyGenerator():
for i in xrange(10):
yield i*i
for i in xrange(12):
yield i*i
for i in xrange(8):
yield i*i
作为 DRY 的忠实信徒,我在这里发现了重复的模式并将其分解为一种方法:
def quadraticRange(n):
for i in xrange(n)
yield i*i
def sillyGenerator():
quadraticRange(10)
quadraticRange(12)
quadraticRange(8)
...这当然行不通。父级必须在循环中调用新函数,产生结果:
def sillyGenerator():
for i in quadraticRange(10):
yield i
for i in quadraticRange(12):
yield i
for i in quadraticRange(8):
yield i
...比以前更长了!
如果我想将生成器的一部分推送到函数中,我总是需要这个相当冗长的两行包装器来调用它。如果我想支持 send(),那就更糟了:
def sillyGeneratorRevisited():
g = subgenerator()
v = None
try:
while True:
v = yield g.send(v)
catch StopIteration:
pass
if v < 4:
# ...
else:
# ...
这还没有考虑传入异常。每次都是相同的样板!然而,一个人不能应用 DRY 并将这个相同的代码分解为一个函数,因为......你需要样板来调用它!我想要的是这样的:
def sillyGenerator():
yield from quadraticRange(10)
yield from quadraticRange(12)
yield from quadraticRange(8)
def sillyGeneratorRevisited():
v = yield from subgenerator()
if v < 4:
# ...
else:
# ...
有没有人能解决这个问题?我有第一次尝试,但我想知道其他人想出了什么。最终,任何解决方案都必须解决主生成器根据发送到生成器的数据结果执行复杂逻辑的示例,并可能对子生成器进行大量调用:我的用例是用于实现的生成器长时间运行的复杂状态机。
【问题讨论】:
-
你能不能简化你真正的问题(不要太多,足够了!)而不是编造一个看起来不太匹配的问题?
-
示例:并非如此。我只想知道如何在没有样板文件的情况下分解复杂的生成器——类似于下面描述的“yield from”语句,但在现有的 Python 中。满足简单情况的技巧是不够的:(