Python 是否具有三元条件运算符?

如果 Python 没有三元条件运算符,是否可以使用其他语言构造来模拟一个?

答案

是的,它是在 2.5 版中添加的 。表达式语法为:

a if condition else b

首先对condition求值,然后根据condition布尔值对ab的任意a求值并返回。如果condition评估为True ,那么a评估和返回,但b被忽略,否则当b评估和返回,但a被忽略。

这使得短路,因为当condition是真实的,只有a评价和b是不是在所有的评估,但是,当condition是假的只有b进行评估, a是不是在所有评估。

例如:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

请注意,条件是表达式 ,而不是语句 。这意味着您不能在条件表达式中使用赋值语句或pass或其他语句

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

但是,您可以使用条件表达式来分配变量,如下所示:

x = a if True else b

将条件表达式视为在两个值之间切换。当您处于 “一个价值或另一个价值” 的情况下,它非常有用,但除此之外别无所求。

如果需要使用语句,则必须使用常规的if 语句而不是条件表达式


请记住,由于某些原因,某些 Pythonista 对此并不满意:

  • 论据的顺序与经典condition ? a : b的顺序不同condition ? a : b来自许多其他语言(例如 C,C ++,Go,Perl,Ruby,Java,Javascript 等)的三元运算符,当人们不熟悉 Python 的 “令人惊讶” 行为时可能会导致错误(它们可能会逆转)参数顺序)。
  • 有些人认为它 “笨拙”,因为它与正常的思维流程相反(先思考条件,然后思考效果)。
  • 风格上的原因。 (尽管'inline if ' 可能确实有用,并且可以使脚本更简洁,但确实会使代码复杂化)

如果您在记住顺序时遇到麻烦,请记住当大声朗读时,您(几乎)说出了您的意思。例如, x = 4 if b > 8 else 9 ,则x = 4 if b > 8 else 9大声读取x = 4 if b > 8 else 9因为x will be 4 if b is greater than 8 otherwise 9

官方文件:

您可以索引到一个元组:

(falseValue, trueValue)[test]

test需要返回TrueFalse
始终将其实现为可能更安全:

(falseValue, trueValue)[test == True]

或者您可以使用内置的bool()来确保布尔值:

(falseValue, trueValue)[bool(<expression>)]

对于 2.5 之前的版本,有个窍门:

[expression] and [on_true] or [on_false]

on_true具有错误的布尔值时,它可能会给出错误的结果。 1 个
尽管这样做确实具有从左到右评估表达式的好处,但在我看来这很清楚。

1. 是否有 C 的等价的 “?:” 三元运算符?

<i><expression 1=""></expression></i> <b>if</b> <i><condition></condition></i> <b>else</b> <i><expression 2=""></expression></i>

a = 1
b = 2

1 if a > b else -1 
# Output is -1

1 if a > b else -1 if a < b else 0
# Output is -1

文档中

条件表达式(有时称为 “三元运算符”)在所有 Python 操作中具有最低的优先级。

x if C else y首先计算条件C不是 x ), x if C else y表达式x if C else y ; 如果C为 true,则对x求值并返回其值;否则,将评估y并返回其值。

有关条件表达式的更多详细信息,请参见PEP 308

从 2.5 版开始新增。

作为Python 增强建议 308 的一部分,2006 年添加了 Python 中条件表达式的运算符。它的形式不同于常见的?:运算符,它的形式是:

<expression1> if <condition> else <expression2>

等效于:

if <condition>: <expression1> else: <expression2>

这是一个例子:

result = x if a > b else y

可以使用的另一种语法(与 2.5 之前的版本兼容):

result = (lambda:y, lambda:x)[a > b]()

懒惰求操作数的地方。

另一种方法是通过索引元组(与大多数其他语言的条件运算符不一致):

result = (y, x)[a > b]

或明确构造的字典:

result = {True: x, False: y}[a > b]

另一种(可靠性较低)但更简单的方法是使用andor运算符:

result = (a > b) and x or y

但是,如果xFalse这将不起作用。

可能的解决方法是按如下所示制作xy列表或元组:

result = ((a > b) and [x] or [y])[0]

要么:

result = ((a > b) and (x,) or (y,))[0]

如果您使用的是字典,则可以使用get(key, default)来代替使用三元条件,例如:

shell = os.environ.get('SHELL', "/bin/sh")

资料来源: ?:维基百科中的 Python

不幸的是,

(falseValue, trueValue)[test]

解决方案没有短路行为;因此,无论条件如何,都会对falseValuetrueValue进行评估。这可能是次优的,甚至是错误的(即trueValuefalseValue都可能是方法,并且有副作用)。

一种解决方案是

(lambda: falseValue, lambda: trueValue)[test]()

(执行会延迟到知道获胜者为止;),但是会在可调用对象和不可调用对象之间引入不一致。此外,使用属性时无法解决问题。

故事就这样 - 在提到的 3 种解决方案之间进行选择是要在具有短路功能,至少使用Зython2.5(恕我直言不再是问题)和不易于 “ trueValue -to-false” 之间进行trueValue错误。

不同编程语言的三元运算符

在这里,我只是试图说明几种编程语言之间在ternary operator一些重要区别。

Javascript 中的三元运算符

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Ruby 中的三元运算符

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Scala 中的三元运算符

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

R 编程中的三元运算符

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

Python 中的三元运算符

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0

对于 Python 2.5 及更高版本,有一种特定的语法:

[on_true] if [cond] else [on_false]

在较旧的 Python 中,未实现三元运算符,但可以对其进行仿真。

cond and on_true or on_false

不过,有一个潜在的问题,如果cond计算结果为True ,并on_true评估为Falseon_false返回,而不是on_true 。如果您想要这种行为,该方法可以,否则请使用以下方法:

{True: on_true, False: on_false}[cond is True] # is True, not == True

可以用以下方法包装:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

并以这种方式使用:

q(cond, on_true, on_false)

它与所有 Python 版本兼容。

您可能经常会发现

cond and on_true or on_false

但这会在 on_true == 0 时导致问题

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

您期望普通三元运算符得到的结果

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1