列表推导首先作为这种形式的语法糖被引入 Python:
L = []
for innerseq in seq:
for item in innerseq:
LOOPS
if CONDITION:
L.append(BODY)
这被转换为:
[BODY for innerseq in seq for item in innerseq LOOPS if CONDITION]
为了使转换更加明显,请注意for
表达式和if
条件的出现顺序与它们在正常循环中的顺序完全相同for
。这就是列表推导使用相同顺序的原因。
当您将循环重写为理解时,唯一改变的是循环主体的位置(它移动到前面,您通常会在此处初始化空容器)。关于循环的其他一切都保持不变。
您喜欢的替代方案(您的“正确方式”)似乎都更加令人困惑。我们要么只是颠倒循环的顺序,要么颠倒理解中每个子句的顺序。即,要么:
[BODY LOOPS[::-1] for item in innerseq for innerseq in seq if CONDITION]
或者
[BODY if CONDITION LOOPS[::-1] for item in innerseq for innerseq in seq]
其中任何一个似乎都是不必要的复杂转换。
另请注意,其他语言在其列表推导中使用相同的循环顺序。这是一些 Clojure:
user=> ; using your suggested "right" order
user=> (for [x (range y) y (range 4)] (+ x y))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: y in this context, compiling:(NO_SOURCE_PATH:1)
user=> ; you need to use the same "wrong" order as Python
user=> (for [y (range 4) x (range y)] (+ x y))
(1 2 3 3 4 5)
这与 Python 相同,尽管 Clojure 将理解的“主体”放在最后。
如果有帮助,想象一下这些for
回路的排列方式就像汽车里程表中的数字一样。最右边的循环旋转最快。