【问题标题】:The order of nested list comprehension and nested generator expression in pythonpython中嵌套列表理解和嵌套生成器表达式的顺序
【发布时间】:2015-01-01 18:30:37
【问题描述】:

我是 Python 新手,被 Python 官方文档中的一段代码弄糊涂了。

unique_words = set(word  for line in page  for word in line.split())

对我来说,它看起来相当于:

unique_words=set()
for word in line.split():
    for line in page:
        unique_words.add(word)

在嵌套循环中定义之前,如何在第一个循环中使用 line?但是,它确实有效。我认为这表明嵌套列表理解和生成器表达式的顺序是从左到右,这与我之前的理解相矛盾。

谁能帮我澄清一下正确的顺序?

【问题讨论】:

  • 你的循环倒退了。 for line in page 部分应该是外循环。
  • 如果你认为你的嵌套循环是等价的,你需要解释一下外循环中line的定义位置。嵌套生成器表达式中的顺序与任何嵌套循环相同。

标签: python generator list-comprehension


【解决方案1】:

你弄错了循环。使用这个:

unique_words = set(word for line in page for word in line.split())
print unique_words

l = []
for line in page:
    for word in line.split():
        l.append(word)
print set(l)

输出:

C:\...>python test.py
set(['sdaf', 'sadfa', 'sfsf', 'fsdf', 'fa', 'sdf', 'asd', 'asdf'])
set(['sdaf', 'sadfa', 'sfsf', 'fsdf', 'fa', 'sdf', 'asd', 'asdf'])

【讨论】:

  • 他是对的! l 应该是一个集合,而不是一个列表。这是一种删除重复值的方法。
  • 请解释被否决的投票,以便我改进答案
【解决方案2】:

word for line in page for word in line.split()

这部分的工作原理是这样的:-

for line in page:
    for word in line.split():
        print word

() 这使它成为`生成器函数 因此,总体声明工作在于:-

def solve():
    for line in page:
        for word in line.split():
            yield word

并且 set() 用于避免重复或重复相同的单词,因为代码旨在获得“唯一单词”。

【讨论】:

  • 很好的答案;我要补充一个事实,即一组用于删除重复项
  • (word for line in page for word in line.split())
【解决方案3】:

您混合了嵌套循环。代码的作用是:

unique_words={}
for line in page:
    for word in line.split():
        unique_words.add(word)

【讨论】:

    【解决方案4】:

    除了强调顺序的正确答案之外,我还要补充一点,我们使用 set 从行中删除重复项以生成“唯一词”。检查thisthis 线程

    unique_words = set(word for line in page for word in line.split())
    print unique_words
    
    l = {}
    for line in page:
        for word in line.split():
            l.add(word)
    print l
    

    【讨论】:

    • {} 不会创建空集。
    【解决方案5】:

    来自官方文档中的tutorial

    列表推导式由包含表达式的括号组成,后跟一个 for 子句,然后是零个或多个 for 或 if 子句。结果将是一个新列表,该列表是在其后面的 for 和 if 子句的上下文中评估表达式而产生的。例如,如果两个列表的元素不相等,则此 listcomp 组合它们: >>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y] [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)] 它相当于: >>> 梳子 = [] >>> 对于 [1,2,3] 中的 x: ...对于 [3,1,4] 中的 y: ...如果 x != y: ... combs.append((x, y)) ... >>> 梳子 [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)] 请注意这两个 sn-ps 中 for 和 if 语句的顺序是如何相同的。

    参见上面引用的最后一句话。

    另请注意,您所描述的构造不是(官方)称为“嵌套列表理解”。嵌套列表推导需要一个列表推导,它在另一个列表推导中,例如(再次来自本教程):

    [[row[i] for row in matrix] for i in range(4)]
    

    您要问的只是一个包含多个 for 子句的列表理解。

    【讨论】:

    • 请注意,第一个示例没有回答问题:xy 是独立的,可以交换,而 OP 的示例中并非如此。
    • @EricDuminil - 它确实回答了这个问题。 OP 想知道在理解中解析多个 for 子句的正确顺序。实际上,OP 已经通过观察行为推断出正确的顺序,但需要确认。还有什么比官方文档更好的确认? xy 是否独立无关紧要。相关部分是将理解展开为其等效的嵌套循环形式,顺便说一句,这正是被接受和投票最多的答案所做的(除了该答案没有引用任何引用来证明它的合理性)。
    • 我仍然认为这是一个糟糕的示例选择(在文档中,而不是您的答案),因为 xy 可以交换。它并没有真正涵盖 OP 的情况,即 word 在 line 并且 line 在 page 中。
    • @EricDuminil - 我明白你在说什么,但关键是它确实涵盖了 OP 的情况,因为重要的是循环的顺序。请注意,虽然xy 是独立的,但它们并不相等。所以如果你交换它们,你会得到不同的结果。您似乎在说,在 OP 的示例中,错误的顺序 break 程序。当然,但是如果它碰巧在一个不能处理最左边元素是4 的元组的程序中,那么在教程示例中也会出错。如果你看懂了教程示例,你就明白了如何解析 OP 的代码 sn-p。
    猜你喜欢
    • 2020-06-06
    • 2019-10-12
    • 2017-05-08
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多