题 Python有三元条件运算符吗?


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


4442


起源


虽然2.5岁以上的蟒蛇正在慢慢漂流到历史,但这里有一个旧的2.5之前的三元算子技巧列表: “Python Idioms”,搜索“条件表达式”文本 。 维基百科 也很有帮助Ж:-) - ジョージ
在上面评论中引用的Python 3.0官方文档中,这被称为“conditional_expressions”,并且是非常密码定义的。该文档甚至不包括术语“三元”,因此除非您确切知道要查找的内容,否则您很难通过Google找到它。该 版本2文档 更有帮助,包括一个链接 “PEP 308”,其中包含许多与此问题相关的有趣的历史背景。 - nobar
“三元”(有三个输入)是这种推动的后果,而不是概念的定义属性。例如:SQL有 case [...] { when ... then ...} [ else ... ] end 为了类似的效果,但根本没有三元组。 - user313114
ISO / IEC 9899(C编程语言标准)第6.5.15节称其为“condtitional operator” - user313114
维基百科在文章中详细介绍了这一点“?”。 - HelloGoodbye


答案:


是的 添加 在2.5版本中。
语法是:

a if condition else b

第一 condition 然后进行评估 a 要么 b 基于的返回 布尔 的价值 condition
如果 condition 评估为 真正  a 返回,否则 b 被退回。

例如:

>>> '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

在这种情况下,你必须使用正常 if 声明而不是条件。


请记住,由于以下几个原因,一些Pythonist对此不满意:

  • 参数的顺序与许多其他语言(例如C,Ruby,Java等)不同,当不熟悉Python的“惊人”行为的人使用它时(可能会颠倒顺序),这可能会导致错误。
  • 有些人觉得它“笨拙”,因为它与正常的思想流程相反(首先考虑条件然后考虑影响)。
  • 文体的原因。

如果您在记住订单时遇到问题,请记住,如果您大声朗读它,您(几乎)会说出您的意思。例如, x = 4 if b > 8 else 9 被大声朗读为 x will be 4 if b is greater than 8 otherwise 9

官方文件:


5299



然而,对于编码员来说,这个命令似乎很奇怪 f(x) = |x| = x if x > 0 else -x 对数学家来说听起来很自然。在大多数情况下你也可以像A一样理解它,除非C然后你应该做B而不是...... - yota
使用时请注意操作顺序。例如,该行 z = 3 + x if x < y else y。如果 x=2 和 y=1,你可能会期望收益率为4,但它实际上会产生1。 z = 3 + (x if x > y else y) 是正确的用法。 - Kal Zekdor
关键是你想要进行额外的评估 后 对条件进行求值,就像在结果中添加一个值一样,你需要在两边添加额外的表达式(z = 3 + x if x < y else 3 + y),或将条件分组(z = 3 + (x if x < y else y) 要么 z = (x if x < y else y) + 3) - Kal Zekdor
@Pred试试 print("OK" if status else "NOT OK") - BusyAnt
我喜欢这种句法排序的模糊讽刺,被称为@yota的人称之为自然。 - nickf


您可以索引到元组:

(falseValue, trueValue)[test]

test 需要回归 真正 要么
总是将它实现为以下可能更安全:

(falseValue, trueValue)[test == True]

或者你可以使用内置的 bool() 保证一个 布尔 值:

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

594



请注意,这个总是评估所有内容,而if / else构造只评估获胜表达式。 - SilverbackNet
(lambda: print("a"), lambda: print("b"))[test==true]() - Dustin Getz
应该注意的是,内在的是什么 []s可以是任意表达式。此外,为了安全起见,您可以通过书面明确地测试真实性 [bool(<expression>)]。该 bool() 功能自v2.2.1起已经存在。 - martineau
这对于代码高尔夫而言非常有用,而不是实际的代码。虽然我已经习惯了它,但是当我做一些明显的事情(比如两个字符串常量之间的选择)时,我有时会使用它来简洁。 - Claudiu
我做了一个类似的技巧 - 只做了一次或两次,但做到了 - 通过索引到字典中 True 和 False 作为关键: {True:trueValue, False:falseValue}[test]  我不知道这是否有任何低效率,但它确实至少避免了整个“优雅”与“丑陋”的辩论。你没有处理布尔值而不是int的歧义。 - JDM


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

[expression] and [on_true] or [on_false]

它可能会给出错误的结果 on_true   具有错误的布尔值。1
虽然它确实有从左到右评估表达式的好处,但在我看来更清楚。

1。 是否有相当于C的“?:”三元运算符?


246



解决方法是使用(test和[true_value]或[false_value])[0],这可以避免这个陷阱。 - ThomasH
三元运算符通常执行得更快(有时为10-25%)。 - volcano
@volcano你有我的来源吗? - OrangeTux
@OrangeTux 这是反汇编代码。使用ThomasH建议的方法会更慢。 - mbomb007


表达式 如果 条件 其他 表达式2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1

157



这和最佳答案有什么区别? - kennytm
这个强调了三元运算符的主要意图:价值选择。它还表明,不止一个三元可以链接在一起形成一个表达式。 - Roy Tinker
@Craig,我同意,但知道在没有括号时会发生什么也是有帮助的。在实际代码中,我也倾向于插入明确的parens。 - Jon Coombs
不知何故,我能够比最佳答案更好地理解这一点。 - abhi divekar


文件

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

表达方式 x if C else y 首先评估条件, C (不是x);如果 C 是真的, X 被评估并返回其值;除此以外, ÿ 被评估并返回其值。

看到 PEP 308 有关条件表达式的更多详细信息

自2.5版以来的新版本。


106





2006年添加了Python中条件表达式的运算符作为其中的一部分 Python Enhancement Proposal 308。它的形式与常见的不同 ?: 运营商,它是:

<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]

另一种(不太可靠),但更简单的方法是使用 and 和 or 运营商:

result = (a > b) and x or y

但如果这不起作用 x 将会 False

一个可能的解决方法是制作 x 和 y 列表或元组,如下所示:

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中


79





@向上:

不幸的是,

(falseValue, trueValue)[test]

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

对此的一个解决方案是

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

(执行延迟到获胜者已知;)),但它引入了可调用和不可调用对象之间的不一致。此外,它不能解决使用属性时的情况。

故事就是这样 - 在3个提到的解决方案之间进行选择是在具有短路功能,使用至少python 2.5(恕我直言不再是问题)和不容易出现“trueValue-evaluates-to-false”之间的权衡错误。


72





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

[on_true] if [cond] else [on_false]

在较旧的Pythons中,没有实现三元运算符,但可以模拟它。

cond and on_true or on_false

虽然,但是存在一个潜在的问题,如果 cond 评估为 True 和 on_true 评估为 False 然后 on_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版本兼容。


48



行为不一样 - q("blob", on_true, on_false) 回报 on_false,而 on_true if cond else on_false 回报 on_true。解决方法是替换 cond 同 cond is not None 在这些情况下,虽然这不是一个完美的解决方案。
为什么不 bool(cond) 代替 cond is True?前者检查真实性 cond,后者检查指针与...的相等性 True 目的。正如@AndrewCecil所强调的那样, "blob" 是真的,但它 is not True。 - Jonas Kölker
哇,看起来真的很hacky! :)从技术上讲,你甚至可以写 [on_false, on_True][cond is True] 所以表达变得更短。 - Arseny


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

在这里,我试着展示一些重要的区别 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

现在你可以看到蟒蛇语言的美丽。它具有高度可读性和可维护性。


39



这个 博客发现python的三元运算符与大多数其他语言不必要地不同。 - JamesThomasMoon1979
Ruby也可以使用 a = true ? 1 : 0 - rneves
“现在你可以看到python语言的美妙之处。它具有高度的可读性和可维护性。”我没有看到这句话的相关性,也没有看到三元运算符语法如何演示它。 - DaveMongoose
这可能听起来很自以为是;但它本质上说的是,Python语法很可能被一个从未见过三元运算符的人理解,而很少有人会理解更常用的语法,除非他们首先被告知它意味着什么。 - fralau
Algol68:a = .if。 。真正。 。然后。 1 .else。 0 .fi。这也可以表示为a =(。true。| 1 | 0)通常,Algol68是对其后继者的改进。 - Albert van der Horst