Python 列表推导式使用多个 'if

68 投票
5 回答
114459 浏览
提问于 2025-04-17 18:07

我们都知道Python的

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

语法。

不过,关于列表推导式的AST表示法,其实可以有不止一个'if'表达式:

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

有没有人能给我一个Python代码的例子,能生成一个包含多个'if'表达式的AST?

5 个回答

23

使用内置的 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]
79

这个语法允许你使用多个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)

这也意味着你可以在没有for循环的情况下使用多个if语句:

[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 – 列表推导式(这个功能最初被提议加入语言的文档)实际上在示例部分包含了一个双if的推导式:

>>> 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')]
108

只需把它们一个接一个地堆叠起来:

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

这样就会生成11到49之间的所有整数,包括11和49。

撰写回答