具有多个'if'的python列表理解

时间:2013-03-06 13:11:58

标签: python if-statement list-comprehension

我们都知道python的

[f(x) for x in y if g(x)]

语法。

然而 列表理解的AST表示有多个'if'表达式的空间:

comprehension = (expr target, expr iter, expr* ifs)

有人可以给我一个python代码示例,它会产生一个带有多个'if'表达式的AST吗?

4 个答案:

答案 0 :(得分:46)

将它们堆叠起来:

[i for i in range(100) if i > 10 if i < 50]

生成11到49之间的整数。

答案 1 :(得分:45)

语法允许多个if语句,因为你可以在for循环中混合它们:

[j for i in range(100) if i > 10 for j in range(i) if j < 20]

理解组件应该被视为嵌套语句,上面翻译为:

lst = []
for i in range(100):
    if i > 10:
        for j in range(i):
            if j < 20:
                lst.append(j)

这也意味着您可以使用多个if语句而不会出现for个循环:

[i for i in range(100) if i > 10 if i < 20]

虽然非敏感(只使用and或链式运算符组合),但它确实会转换为合法的嵌套语句集:

lst = []
for i in range(100):
    if i > 10:
        if i < 20:
            lst.append(i)

语法和解析器并没有特别禁止这样的用法,就像Python不允许你嵌套if语句一样。

请注意,PEP 202 – List Comprehensions(将此功能添加到语言中的原始提案文档)实际上包含示例部分中的双重理解:

>>> print [(i, f) for i in nums for f in fruit if f[0] == "P" if i%2 == 1]
[(1, 'Peaches'), (1, 'Pears'), (3, 'Peaches'), (3, 'Pears')]

答案 2 :(得分:9)

使用内置的all()允许您在迭代中放置多个布尔表达式或函数,并坚持您的理解。我认为这是一个非常使用的内置并且它保持高可读性。

>>> [x for x in range(20) if all([1 < x < 10, not x & 1])]
[2, 4, 6, 8]

或者

>>> [x for x in range(20) if all([foo(x), bar(x)])]
如果只需要满足一个条件,那么内置的any()在这里也会很好用:

>>> [x for x in range(20) if any([1 < x < 10, not x & 1])]
[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18]

答案 3 :(得分:5)

language reference可以更好地了解这一点:

list_comprehension  ::=  expression list_for
list_for            ::=  "for" target_list "in" old_expression_list [list_iter]
list_iter           ::=  list_for | list_if
list_if             ::=  "if" old_expression [list_iter]

正如您所看到的,列表理解是通过最后一个list_iter选项list_iter来定义的。现在这个list_iter可以是列表理解的另一部分或if条件。 if条件本身再次以另一个可选list_iter结束。这对于在同一列表理解中使用可选的if条件链接多个for-parts是必要的。您还可以为.. if X if Y if Z构建list_iter部分,这只是副作用。

因此,虽然不需要单独链接多个if条件的可能性,但它允许以这种方式定义整个语法。