我知道在嵌套列表理解中拥有多个
for
的正确方法如下(Python 3):
lista = [[[1,2],[3],[4,5,6]],[[7],[8,9]]]
flatlista = [i for k in lista for j in k for i in j]
# results with [1, 2, 3, 4, 5, 6, 7, 8, 9]
但我的自然语言本能强烈反对。我(错误地)期望代码是:
flatlista = [i for i in j for j in k for k in lista]
错误的版本听起来几乎像英语,并且从左到右以一个流的方式阅读。正确的版本需要一些嵌套的阅读技巧,左右跳跃才能涵盖含义。
为什么是这个语法?为什么语言要这样构建?
因为这就是 PEP 202 -- 列表推导式 设置的。然而,PEP 并没有完全解释为什么,因为它是事后才创建的;在 PEP 创建之前,甚至在 PEP 流程创建之前,讨论就已经在开发清单上进行了。
首先,该顺序反映了您在 Python 代码中嵌套
for
循环和 if
语句的顺序:
for k in lista:
for j in k:
for i in j:
如果您已经习惯了that订购,这会变得非常自然。
看看关于该功能的第一次讨论,其他语言中似乎有排序的先例。事实上,Haskell 具有相同的顺序:每个连续的生成器都会细化前一个生成器的结果。
当然,在某个时候 Tim Peters(提案发起人)表示今天使用的顺序对他来说是显而易见的,请参阅这篇文章:
我已经多次发布了我对今天的 Python 的建议翻译, 其目的是从字面上理解,而不是暗示性的。这个巢穴 “for”与最左边最外面的循环,所以钉住了关于 对所有级别的语义进行排序。为什么这成为了一个争论点 水平超出了我的水平。
backwards。
[ginjoint for town in world for ginjoint in town]
因为谁希望他们的编程语言听起来像有史以来最伟大的电影?
嗯,是的 - 似乎应该将其读作扁平的 for 循环
paragraph = ["hi stackoverflow devs!", "i know there is a comment", "that comment is not the same"]
letters = []
for sentence in paragraph:
for word in sentence.split(" "):
if word != "comment":
for letter in word:
letters.append(letter)
letters = [letter for sentence in paragraph for word in sentence.split(" ") if word != "comment" for letter in word]
print(letters)