为什么 Python、Go 和 Rust 都不支持三元运算符?( 二 )


由于得票太分散,因此,这个 PEP 在当时被拒绝了 。PEP 中写道:“Python 的一个设计原则是在不确定采取哪条路线时,则保持现状 。”
and-or 用于条件选择的问题以上的投票事件发生在 2004 年 3 月,但是,在 PEP 被拒绝后,相关话题的讨论并未平息,因为大家总想找一种简洁的方式来替换“if-else“ 。
时间到了 2005 年 9 月,邮件组中有人提议在  Py3.0 中变更"and"与"or"操作符的逻辑,提议将"and" 和 "or" 运算符简化成始终返回布尔值,而不是返回最后一个被求值的参数 。
之所以发起这个提议,原因是他使用了<condition> and <expression1> or <expression2>的方式来实现条件判断与选择 。但是这种写法在 Python 中的行为跟有些语言并不一样,使用不严谨的话,可能会酿成 Bug!
看看下面的两个例子,你觉得它们会得到什么结果呢?
a = True and True or "Python猫"b = True and False or "Python猫"对于<condition> and <expression1> or <expression2> ,若 condition 为假,则会直接对 expression2 求值并返回结果;若 condition 为真,则先对 expression1 求值,若也为真,则不会继续对 expression2 求值,若 expression1 不为真,则对 expression2 求值 。
因此,上述例子得到的 a 是“True”,而 b 会得到“Python猫” 。
本系列的《Python 为什么能支持任意的真值判断? 》介绍过 Python 在真值判断的特殊之处,运用到以上结构中,将出现更不易察觉的问题 。比如,该邮件的作者就是遇到了“expression1”为复数“0+4i”,这个数的真值判断为 False,因此导致最后返回的不是预期的“expression1”,而是“expression2”!
在没有更好的方案前,“and-or”是比较常见的条件选择写法,PEP-308 也提及了它,也指出了当“expression1”为假的情况,还认为这种方案是丑陋和令人费解的 。
这封邮件再次引发了社区对条件选择语法的讨论,大佬们纷纷登场 。
以我现在的视角分析,其实就是开发者们不满足于“if-else”的现状,但是当时流行的“and-or”写法并不够好,因此,大家期望 Python 设计出新的规范性语法,来解决这个痛点 。
与众不同的条件表达式在经过 10 天的邮件讨论后,Guido van Rossum 最终决定添加一个条件表达式,语法形式为X if C else Y  。因此,PEP-308 被重开和更新,并很快就在次年的 2.5 版本中实现了 。
前文已提到过这个让一些人感觉不舒服的方案了,因为它没有将条件判断逻辑放在最前面 。
那么,为什么最后的胜者会是它呢?这是不是最优的设计呢?
不可否认,起到决定性作用的原因是 Guido 。由于社区在一年半前投票时没有形成多数意见,因此他行使 BDFL (终身仁慈独裁者)的决策权力,裁定出一个他认为是最佳的方案 。
X if C else Y 非常易于理解,可读性高 。它延续了“明确优于隐式”的风格,使用了直观口语化的“if-else”,而不是引入可能引起混淆的标点符号,就像 Python 选择“and”和“or”两个单词,而不是“&&”和“||”两个符号,它们有着异曲同工之妙 。
虽然调整后的语法顺序让人不太习惯,但其实这样的实现却大有好处 。首先,它只需复用“if-else”两个关键字,而不需要引入“then”、“when”和其它语法要素,也不像(if <condition>: <expression1> else: <expression2>) 那样的繁琐 。
其次,为了验证X if C else Y 的有效性,Guido 排查了标准库中所有“and-or”组合的写法,发现那些C and X or Y 写法都可以被X if C else Y 替换掉 。标准库的情况,证明了这新的语法是可行的 。
最后,在 PEP-308 提及的原因外,我还想补充一点 。据观察,我发现很多时候我们有一个已初始化的变量,然后需要在出现某个条件时,更新变量的值 。在这种情况下,“else”部分可以被省略,非常便捷 。
my_str = ""# 中间存在其它代码逻辑# 当 condition 为真时,变量会被重新赋值my_str = "Python猫" if condition回顾这段历史,我们可以梳理出一条线索:Python 没有设计三元运算符“?:”,主要是因为它不符合 Python 明确直观的设计风格 。最后采用X if C else Y 这种设计,主要的意图其实是消除“and-or”写法的隐患,这种设计简明易读,而且还有<expression> if <condition> 简化写法的妙用 。


推荐阅读