我可以通过举一个例子来最好地提出我的问题。假设我想使用列表推导从两个循环生成一组 3 元素元组,如下所示:
[ (y+z,y,z) for y in range(10) if y%2==0 for z in range(20) if z%3==0 ]
这有效,给我
[(0, 0, 0), (3, 0, 3), (6, 0, 6), (9, 0, 9), (12, 0, 12), (15, 0, 15), ... ]
不过,我想知道是否有一种方法可以更干净地做到这一点,例如
[ (x,y,z) for y in range(10) if y%2==0 for z in range(20) if z%3==0 ... somehow defining x(y,z) ... ]
我认为像这样的东西更干净,特别是因为我真正需要做的事情比我在这里给出的例子要复杂得多。我尝试过的所有方法都给出了语法错误。
您可以执行以下操作:
自 Python 3.9 以来,此功能已进行了优化:https://docs.python.org/3/whatsnew/3.9.html#optimizations
我将跳过除法并仅明确生成所需的倍数。
现在您可以使用
itertools.product
两个生成器了。无论命名的表达式有多复杂,在所描述的场景中都没有理由这样做。如果表达式很复杂,只需分解定义
tuple
:如果你实际上既测试又生成值(因此必须将其分配给名称),当然,使用Andrej 的解决方案,然后执行以下操作:
或者如果你不关心
x
列表计算范围的泄漏,那么甚至更简单/更简洁的基于海象(:=
)的方法:但是当您只需要该值一次时,除非您有一个非常好的名称以便清楚起见,否则命名它不会有什么好处(并且我认为在这种情况下为生成的值定义一个简单的命名元组可能是可行的方法,而不是仅在列表推导中给它一个有用的名称)。
如果表达式足够复杂,需要进行更多计算,那么它就足够复杂了,您可能应该放弃列表推导,而手动将其扩展为 for 循环,例如:
或者将其分解为生成器函数:
您可以调用
do_whatever()
(如果您不能逐一迭代结果进行处理,则立即list(do_whatever())
收集结果)。list