具有多个'if'的python列表理解
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15248272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python list comprehension with multiple 'if's
提问by Stefan
We all know python's
我们都知道python的
[f(x) for x in y if g(x)]
syntax.
句法。
However the ASTrepresentation of list comprehension has room for more than one 'if' expression:
然而 ,列表推导式的 AST表示可以容纳多个“if”表达式:
comprehension = (expr target, expr iter, expr* ifs)
Can somebody give me an example of python code that would produce an AST with more than one 'if' expression?
有人能给我一个 python 代码的例子,它会产生一个带有多个“if”表达式的 AST?
采纳答案by Emil Vikstr?m
Just stack them after one another:
只需将它们一个一个地堆叠起来:
[i for i in range(100) if i > 10 if i < 50]
Produces the integers between 11 and 49, inclusive.
生成 11 到 49(含)之间的整数。
回答by Martijn Pieters
The grammar allows for multiple if statements because you can mix them between the for loops:
语法允许多个 if 语句,因为您可以在 for 循环之间混合它们:
[j for i in range(100) if i > 10 for j in range(i) if j < 20]
The comprehension components should be viewed as nested statements, the above translates to:
理解组件应该被视为嵌套语句,上面翻译为:
lst = []
for i in range(100):
if i > 10:
for j in range(i):
if j < 20:
lst.append(j)
This also means that you can use multiple ifstatements without forloops in between:
这也意味着您可以使用多个if语句for,中间没有循环:
[i for i in range(100) if i > 10 if i < 20]
Although non-sensical (just combine those using andor with chained operators), it does translate to a legal nested set of statements still:
尽管没有意义(只是将那些使用and或与链式运算符结合起来),它仍然转换为合法的嵌套语句集:
lst = []
for i in range(100):
if i > 10:
if i < 20:
lst.append(i)
The grammar and parser do not specifically disallowsuch usage, in the same way that Python doesn't disallow you to nest ifstatements.
语法和解析器并没有明确禁止这种用法,就像 Python 不允许嵌套if语句一样。
Note that PEP 202 – List Comprehensions(the original proposal document that added this feature to the language) actually includes a double-if comprehension in the examples section:
请注意,PEP 202 – List Comprehensions(将这个特性添加到语言中的原始提案文档)实际上在示例部分包含了一个双重 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')]
回答by poke
The language referencegives a better idea about this:
该语言参考提供了有关这个更好的主意:
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]
As you can see the list comprehension is defined with an optional list_iterat the end—a single list_iter. Now this list_itercan either be another for-part of the list comprehension or an if-condition. The if-condition itself again ends with another optional list_iter. This is essential to make it possible to chain multiple for-parts with optional if-conditions in the same list comprehension. The fact that you could also construct an .. if X if Y if Zpart for the list_iteris just a side effect.
正如您所看到的,列表推导式list_iter在末尾定义了一个可选的list_iter. 现在这list_iter可以是列表推导式的另一个 for-part 或 if 条件。if 条件本身再次以另一个 optional 结束list_iter。这对于在同一个列表推导式中使用可选的 if 条件链接多个 for 部分是必不可少的。事实上,你也可以为 构建一个.. if X if Y if Z部分list_iter只是一个副作用。
So, while the possibility to chain multiple if-conditions alone is not needed, it allows the whole grammar to be defined that way.
因此,虽然不需要单独链接多个 if 条件的可能性,但它允许以这种方式定义整个语法。
回答by kylie.a
Using the built in all()allows you to place multiple Boolean expressions or functions in an iterable and stick in your comprehension. I think it's a pretty under used built in and it keeps readability high.
使用内置all()函数可以让您将多个布尔表达式或函数放在一个可迭代对象中并坚持您的理解。我认为这是一个相当未使用的内置工具,它保持了很高的可读性。
>>> [x for x in range(20) if all([1 < x < 10, not x & 1])]
[2, 4, 6, 8]
Or
或者
>>> [x for x in range(20) if all([foo(x), bar(x)])]
the any()built in also would work well here if only one condition needed to be satisfied:
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]

