Python语言技巧之三元运算符使用介绍


Posted in Python onMarch 04, 2013

python不支持C/C++中的三元操作符 ?:,替代的方法是 ...if... else...
举例,用下面的语法实现求三个数的最小值。
nD1 if nD1 < ( nD2 if nD2<nD3 else nD3) else (nD2 if nD2 < nD3 else nD3)

python三元运算符的正确方法

因为下周要用php写项目,所以周末在家里重新看php的语法,看到三元描述符,突然想起来python是没有三元描述符的,印象中依稀记得有模拟的实现,于是上网上搜了一下。
(对应C语言的 X ? V1:V2)

其中一种是:

(X and V1) or V2

正常情况下是不会有错误的,但是文章中也提到了,当V1=""时,就会有问题
比如

print (True and '') or 'V' 
print (False and '') or 'V'

输出永远都是: V

完美的解决方案是在《python核心编程中提到的》:

V1 if X else V2

原文如下:

如果你来自 C/C++ 或者是 Java 世界, 那么你很难忽略的一个事实就是 Python 在很长的一
段时间里没有条件表达式(C ? X : Y), 或称三元运算符. ( C 是条件表达式; X 是 C 为 True 时
的结果, Y 是 C 为 False 时的结果) 贵铎·范·罗萨姆一直拒绝加入这样的功能, 因为他认为应
该保持代码简单, 让程序员不轻易出错. 不过在十年多后, 他放弃了, 主要是因为人们试着用
and 和 or 来模拟它, 但大多都是错误的. 根据 FAQ , 正确的方法(并不唯一)是
(C and [X] or [Y])[0] . 唯一的问题是社区不同意这样的语法. (你可以看一看 PEP 308, 其
中有不同的方案.) 对于Python 的这一问题,人们表达了极大的诉求.
贵铎·范·罗萨姆最终选择了一个最被看好(也是他最喜欢)的方案, 然后把它运用于标准库中
的一些模块. 根据 PEP , "这个评审通过考察大量现实世界的案例, 包含不同的应用, 以及由不同
程序员完成的代码." 最后 Python 2.5 集成的语法确定为: X if C else Y .

如上文所说,该语法在python2.5才被加入,但是因为平时也不会用到2.4及以前的版本,所以也就够用了~

现在大部分高级语言都支持“?”这个三元运算符(ternary operator),它对应的表达式如下:condition ? value if true : value if false。很奇怪的是,这么常用的运算符python居然不支持!诚然,我们可以通过if-else语句表达,但是本来一行代码可以完成的非要多行,明显不够简洁。没关系,在python里其实还是有对应的表达方式的。

    举个例子:char *ret = (x!=0) ? "True" : "False"这行代码对应的python形式就是ret = (x and "True") or "False"(很简单吧,事实上括号可以去掉)。运行时,python虚拟机会对赋值符右边的布尔表达式(注意这里并非三元表达式)求值,返回值是最后一个被分析到的值。为什么是“最后一个被分析到的”而不是表达式中“最后一个”呢?因为布尔表达式有一个短路效应,比如a or b,如果a为真那么就不会分析b了。嗯,估计现在大家差不多明白了这行python代码的原理了。如果x为真,由于字符串“True”也为真,于是返回"True",反之,x为假,那么就没必要看字符串"True"了(短路效应),直接返回"False"。

    不难看出,三元运算在python中事实上可以通过借用布尔求值表达。然后,有时会有点小问题。举个例子,char *ret = x ? "" or "VAL"。根据前面的例子,我们很自然想到在python里应该这样写,ret = x and "" or "VAL"。错了!不管x的布尔求值是真还是假,ret得到的总是"VAL"。奇怪么?不奇怪,因为在python中对空字符串的布尔求值为false,这样x and ""永远都是false,所以ret得到的自然总是"VAL"了。解决这个问题有两种办法,第一种,也是我喜欢的一种,就是写成ret = not x and "VAL" or ""。第二种,麻烦一点ret=x and [""] or ["VAL"],然后每次取ret[0]作为返回值,这是因为[""]在布尔求值时值为true。

    讨论一:第一种方法代码明显要简洁,效率也高,那么还有必要使用第二种么?当然,第一种办法有局限性,只有当我们非常明确其中一个值布尔求值时不可能为false时才能使用。在我们的示例中,由于"VAL"肯定返回true所以可以使用。如果是两个变量呢,像这样ret=x and val1 or val2,你就只能老老实实写成ret=x and [val1] or [val2],然后取ret[0]作为结果了。因为这行语句所表达的不是“当x为真返回val1,否则返回val2”,而是“当x为真并且val1为真返回val2,否则返回val2”。

    讨论二:大家都知道python里有list和tuple,前面这行代码ret=x and [""] or ["VAL"]我们就是通过list解决,有的人可能偏爱tuple,于是就会这样写ret=x and ("") or ("VAL")。错了!这里ret[0]永远都是空字符串(在2.5上测试)。这是我比较faint的一点,为啥[""]为真而("")为假呢?

    最后,附上python对典型数值的布尔求值结果,这对我们书写三元运算的等价语句很有用。


输入 布尔求值
1,-1,[“”] True
0, “”, None, [], (), {}, (“”) False
Python 相关文章推荐
pymongo给mongodb创建索引的简单实现方法
May 06 Python
Django中模型Model添加JSON类型字段的方法
Jun 17 Python
详解Python实现按任意键继续/退出的功能
Aug 19 Python
Python面向对象之继承代码详解
Jan 29 Python
Python使用wget实现下载网络文件功能示例
May 31 Python
python3 flask实现文件上传功能
Mar 20 Python
python读取word文档,插入mysql数据库的示例代码
Nov 07 Python
对python tkinter窗口弹出置顶的方法详解
Jun 14 Python
利用Tensorflow构建和训练自己的CNN来做简单的验证码识别方式
Jan 20 Python
Python编程快速上手——Excel到CSV的转换程序案例分析
Feb 28 Python
浅谈keras中Dropout在预测过程中是否仍要起作用
Jul 09 Python
Python可视化神器pyecharts之绘制箱形图
Jul 07 Python
python解决字典中的值是列表问题的方法
Mar 04 #Python
python实现的各种排序算法代码
Mar 04 #Python
python 获取本机ip地址的两个方法
Feb 25 #Python
把大数据数字口语化(python与js)两种实现
Feb 21 #Python
python正则表达式修复网站文章字体不统一的解决方法
Feb 21 #Python
Python操作Mysql实例代码教程在线版(查询手册)
Feb 18 #Python
python的常见命令注入威胁
Feb 18 #Python
You might like
PHP静态新闻列表自动生成代码
2007/06/14 PHP
php中修改浏览器的User-Agent来伪装你的浏览器和操作系统
2011/07/29 PHP
php判断文件上传类型及过滤不安全数据的方法
2014/12/17 PHP
php简单实现MVC
2015/02/05 PHP
PHP开发中csrf攻击的简单演示和防范
2017/05/07 PHP
php+mysql+ajax 局部刷新点赞/取消点赞功能(每个账号只点赞一次)
2020/07/24 PHP
js定时调用方法成功后并停止调用示例
2014/04/08 Javascript
从零学JSON之JSON数据结构
2014/05/19 Javascript
文本框倒叙输入让输入框的焦点始终在最开始的位置
2014/09/01 Javascript
实例讲解JQuery中this和$(this)区别
2014/12/08 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
2015/10/23 Javascript
IE下JS保存图片的简单实例
2016/07/15 Javascript
JS弹出新窗口被拦截的解决方法
2016/08/09 Javascript
Angular ng-repeat遍历渲染完页面后执行其他操作详细介绍
2016/12/13 Javascript
canvas实现流星雨的背景效果
2017/01/13 Javascript
又拍云 Node.js 实现文件上传、删除功能
2018/10/28 Javascript
JS异步执行结果获取的3种解决方式
2019/02/19 Javascript
vue watch关于对象内的属性监听
2019/04/22 Javascript
微信小程序商品详情页底部弹出框
2019/11/22 Javascript
react 不用插件实现数字滚动的效果示例
2020/04/14 Javascript
基于javascript canvas实现五子棋游戏
2020/07/08 Javascript
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
[51:10]VP vs VGJ.S 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python模拟鼠标拖动操作的方法
2015/03/11 Python
python文件与目录操作实例详解
2016/02/22 Python
python实现对图片进行旋转,放缩,裁剪的功能
2019/08/07 Python
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
2020/04/17 Python
python从ftp获取文件并下载到本地
2020/12/05 Python
医学求职信
2014/05/28 职场文书
保护地球的标语
2014/06/17 职场文书
建筑工地大门标语
2014/06/18 职场文书
县委常委班子专题民主生活会查摆问题及整改措施
2014/09/27 职场文书
2015年音乐教师个人工作总结
2015/05/20 职场文书
2016年9月份红领巾广播稿
2015/12/21 职场文书
《夸父追日》教学反思
2016/02/20 职场文书
自动在Windows中运行Python脚本并定时触发功能实现
2021/09/04 Python