关于python:是否可以在列表解析中使用’else’?

Is it possible to use 'else' in a list comprehension?

本问题已经有最佳答案,请猛点这里访问。

下面是我试图变成清单理解的代码:

1
2
3
4
5
6
table = ''
for index in xrange(256):
    if index in ords_to_keep:
        table += chr(index)
    else:
        table += replace_with

有没有一种方法可以将else语句添加到这种理解中?

1
table = ''.join(chr(index) for index in xrange(15) if index in ords_to_keep)


语法a if b else c是python中的三元运算符,如果条件b为真,则计算为a;否则,计算为c。它可用于理解陈述:

1
2
>>> [a if a else 2 for a in [0,1,0,3]]
[2, 1, 2, 3]

以你为例,

1
2
table = ''.join(chr(index) if index in ords_to_keep else replace_with
                for index in xrange(15))


如果您想要一个else,您不想过滤列表理解,您希望它遍历每个值。您可以使用true-value if cond else false-value作为语句,并从末尾删除过滤器:

1
table = ''.join(chr(index) if index in ords_to_keep else replace_with for index in xrange(15))


要在python编程中使用elsein list理解,您可以尝试下面的代码片段。这将解决您的问题,该代码片段在python 2.7和python 3.5上进行了测试。

1
obj = ["Even" if i%2==0 else"Odd" for i in range(10)]


是的,在条件表达式(三元运算符)的list理解中,可以在python中使用else

1
2
>>> [("A" if b=="e" else"c") for b in"comprehension"]
['c', 'c', 'c', 'c', 'c', 'A', 'c', 'A', 'c', 'c', 'c', 'c', 'c']

这里,括号"()"只是为了强调条件表达式,它们不一定是必需的(运算符优先级)。

另外,可以嵌套多个表达式,从而导致更多的elses和更难读取的代码:

1
2
3
>>> ["A" if b=="e" else"d" if True else"x" for b in"comprehension"]
['d', 'd', 'd', 'd', 'd', 'A', 'd', 'A', 'd', 'd', 'd', 'd', 'd']
>>>

在相关注释中,理解还可以在结尾处包含其自身的if条件:

1
2
3
4
>>> ["A" if b=="e" else"c" for b in"comprehension" if False]
[]
>>> ["A" if b=="e" else"c" for b in"comprehension" if"comprehension".index(b)%2]
['c', 'c', 'A', 'A', 'c', 'c']

条件?是的,可以有多个ifs,实际上也可以有多个fors:

1
2
3
4
>>> [i for i in range(3) for _ in range(3)]
[0, 0, 0, 1, 1, 1, 2, 2, 2]
>>> [i for i in range(3) if i for _ in range(3) if _ if True if True]
[1, 1, 2, 2]

(在python中,单下划线_是一个有效的变量名(标识符),这里只是用来表示它实际上没有被使用。在交互模式下有特殊意义)

可以将其用于其他条件表达式,但不能真正使用:

1
2
3
4
5
6
>>> [i for i in range(3)]
[0, 1, 2]
>>> [i for i in range(3) if i]
[1, 2]
>>> [i for i in range(3) if (True if i else False)]
[1, 2]

还可以嵌套理解以创建"多维"列表("数组"):

1
2
>>> [[i for j in range(i)] for i in range(3)]
[[], [1], [2, 2]]


最后但并非最不重要的是,理解不仅限于创建list,即elseif也可以在set理解中以同样的方式使用:

1
2
>>> {i for i in"set comprehension"}
{'o', 'p', 'm', 'n', 'c', 'r', 'i', 't', 'h', 'e', 's', ' '}

和一个dictionary理解:

1
2
>>> {k:v for k,v in [("key","value"), ("dict","comprehension")]}
{'key': 'value', 'dict': 'comprehension'}

同样的语法也用于生成器表达式:

1
2
3
4
>>> for g in ("a" if b else"c" for b in"generator"):
...     print(g, end="")
...
aaaaaaaaa>>>

它可以用来创建一个tuple(没有元组理解)。


进一步阅读:

  • 关于数据结构的python教程
    • 列表推导
    • 集合
    • 辞典

很好的答案,但只想提到一个gotcha,"pass"关键字在列表理解的if/else部分不起作用(如上面提到的示例中所发布的那样)。

1
2
3
4
5
6
7
8
9
#works
list1 = [10, 20, 30, 40, 50]
newlist2 = [x if x > 30 else x**2 for x in list1 ]
print(newlist2, type(newlist2))

#but this WONT work
list1 = [10, 20, 30, 40, 50]
newlist2 = [x if x > 30 else pass for x in list1 ]
print(newlist2, type(newlist2))

这是在Python3.4上尝试和测试的。错误如下:

1
2
newlist2 = [x if x > 30 else pass for x in list1 ]                                    
SyntaxError: invalid syntax

所以,尽量避免在列表理解中通过ES


Also, would I be right in concluding that a list comprehension is the most efficient way to do this?

也许吧。列表理解并不是天生的计算效率。它仍在线性时间内运行。

根据我的个人经验:在处理大型数据集时,我已经大大减少了计算时间,方法是用上面的for循环/列表附加类型结构替换列表理解(特别是嵌套的理解)。在这个应用程序中,我怀疑您会注意到一个不同。