Python 中的 else详解


Posted in Python onApril 23, 2016

我们都知道 Python 中else的基本用法是在条件控制语句中的 if...elif...else...,但是 else 还有两个其它的用途,一是用于循环的结尾,另一个是用在错误处理的 try 中。这原本是 Python 的标准语法,但由于和大部分其它编程语言的习惯不太一样,致使人们有意或无意地忽略了这些用法。另外,对于这些用法是否符合 0×00 The Zen of Python 的原则以及该不该广泛使用也存在很多争议。例如在我看到的两本书里(Effective Python VS Write Idiomatic Python),两位作者就分别对其持有截然不同的态度。

循环中的 else

跟在循环后面的 else 语句只有在当循环内没出现 break,也就是正常循环完成时才会执行。首先我们来看一个插入排序法的例子:

from random import randrange
def insertion_sort(seq):
  if len(seq) 1:
    return seq
  _sorted = seq[:1]
  for i in seq[1:]:
    inserted = False
    for j in range(len(_sorted)):
      if i _sorted[j]:
        _sorted = [*_sorted[:j], i, *_sorted[j:]]
        inserted = True
        break
    if not inserted:
      _sorted.append(i)
  return _sorted
 
print(insertion_sort([randrange(1, 100) for i in range(10)]))

[8, 12, 12, 34, 38, 68, 72, 78, 84, 90]

在这个例子中,对已排序的 _sorted 元素逐个与 i 进行比较,若 i 比已排序的所有元素都大,则只能排在已排序列表的最后。这时我们就需要一个额外的状态变量 inserted 来标记完成遍历循环还是中途被 break,在这种情况下,我们可以用 else 来取代这一状态变量:

def insertion_sort(seq):
  if len(seq) 1:
    return seq
  _sorted = seq[:1]
  for i in seq[1:]:
    for j in range(len(_sorted)):
      if i _sorted[j]:
        _sorted = [*_sorted[:j], i, *_sorted[j:]]
        break
    else:
      _sorted.append(i)
  return _sorted
print(insertion_sort([randrange(1, 100) for i in range(10)]))

[1, 10, 27, 32, 32, 43, 50, 55, 80, 94]

我认为这是一个非常酷的做法!不过要注意的是,除了 break 可以触发后面的 else 语句,没有循环的时候也会:

while False:
  print("Will never print!")
else:
  print("Loop failed!")


Loop failed!

错误捕捉中的 else

try...except...else...finally 流程控制语法用于捕捉可能出现的异常并进行相应的处理,其中 except 用于捕捉 try 语句中出现的错误;而 else 则用于处理没有出现错误的情况;finally 负责 try 语句的”善后工作“ ,无论如何都会执行。可以通过一个简单的例子来展示:

def divide(x, y):
  try:
    result = x / y
  except ZeroDivisionError:
    print("division by 0!")
  else:
    print("result = {}".format(result))
  finally:
    print("divide finished!")
divide(5,2)
print("*"*20)
divide(5,0)

result = 2.5
divide finished!
********************
division by 0!
divide finished!

当然,也可以用状态变量的做法来替代 else:

def divide(x, y):
  result = None
  try:
    result = x / y
  except ZeroDivisionError:
    print("division by 0!")
  if result is not None:
    print("result = {}".format(result))
  print("divide finished!")
 
divide(5,2)
print("*"*20)
divide(5,0)

result = 2.5
divide finished!
********************
division by 0!
divide finished!

总结

有人觉得 else 的这些用法违反直觉或者是 implicit 而非 explicit,不值得提倡。但我觉得这种”判决“需要依赖具体的应用场景以及我们对 Python 的理解,并非一定要对新人友好的语法才算是 explicit 的。当然也不推荐在所有地方都使用这个语法,for/while...else 最大的缺点在于 else 是需要与 for/file 对齐的,如果是多层嵌套或者循环体太长的情况,就非常不适合用 else(回忆一下游标卡尺的梗就知道了:P)。只有在一些简短的循环控制语句中,我们通过 else 摆脱一些累赘的状态变量,这才是最 Pythonic 的应用场景!

Python 相关文章推荐
python函数局部变量用法实例分析
Aug 04 Python
Python实现对象转换为xml的方法示例
Jun 08 Python
Python之csv文件从MySQL数据库导入导出的方法
Jun 21 Python
python读取LMDB中图像的方法
Jul 02 Python
python数据批量写入ScrolledText的优化方法
Oct 11 Python
Flask框架web开发之零基础入门
Dec 10 Python
深入了解Python枚举类型的相关知识
Jul 09 Python
python3 中的字符串(单引号、双引号、三引号)以及字符串与数字的运算
Jul 18 Python
python zip()函数使用方法解析
Oct 31 Python
去除python中的字符串空格的简单方法
Dec 22 Python
Python 多线程之threading 模块的使用
Apr 14 Python
详解如何用Python实现感知器算法
Jun 18 Python
Python 探针的实现原理
Apr 23 #Python
一键搞定python连接mysql驱动有关问题(windows版本)
Apr 23 #Python
Linux 发邮件磁盘空间监控(python)
Apr 23 #Python
web.py 十分钟创建简易博客实现代码
Apr 22 #Python
在windows下快速搭建web.py开发框架方法
Apr 22 #Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 #Python
Python开发之快速搭建自动回复微信公众号功能
Apr 22 #Python
You might like
深入分析使用mysql_fetch_object()以对象的形式返回查询结果
2013/06/05 PHP
php自动给网址加上链接的方法
2015/06/02 PHP
[原创]php token使用与验证示例【测试可用】
2017/08/30 PHP
ExtJS Grid使用SimpleStore、多选框的方法
2009/11/20 Javascript
Jquery中获取iframe的代码
2011/01/11 Javascript
JavaScript中__proto__与prototype的关系深入理解
2012/12/04 Javascript
JQuery控制radio选中和不选中方法总结
2015/04/15 Javascript
微信WeixinJSBridge API使用实例
2015/05/25 Javascript
简单谈谈JS数组中的indexOf方法
2016/10/13 Javascript
yarn与npm的命令行小结
2016/10/20 Javascript
js实现页面刷新滚动条位置不变
2016/11/27 Javascript
JavaScript实现类似淘宝的购物车效果
2017/03/16 Javascript
jQuery Validate 无法验证 chosen-select元素的解决方法
2017/05/17 jQuery
详解JavaScript数组过滤相同元素的5种方法
2017/05/23 Javascript
原生JS实现列表子元素顺序反转的方法分析
2018/07/02 Javascript
Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
2014/06/04 Python
Python批量按比例缩小图片脚本分享
2015/05/21 Python
Python 加密的实例详解
2017/10/09 Python
Python可变参数*args和**kwargs用法实例小结
2018/04/27 Python
Python实现网页截图(PyQT5)过程解析
2019/08/12 Python
python pandas利用fillna方法实现部分自动填充功能
2020/03/16 Python
python+adb+monkey实现Rom稳定性测试详解
2020/04/23 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
2020/08/18 Python
Pandas DataFrame求差集的示例代码
2020/12/13 Python
css3的transition属性详解
2014/12/15 HTML / CSS
html5/css3响应式页面开发总结
2018/10/16 HTML / CSS
数据管理员的自我评价分享
2013/11/15 职场文书
中专毕业生的自我鉴定
2013/12/01 职场文书
经典公益广告词
2014/03/13 职场文书
新品发布会策划方案
2014/06/08 职场文书
啦啦队口号大全
2014/06/16 职场文书
云台山导游词
2015/02/03 职场文书
放假通知格式
2015/04/14 职场文书
旅游安全责任协议书
2016/03/22 职场文书
2016创先争优活动党员公开承诺书
2016/03/24 职场文书
2019个人半年工作总结
2019/06/21 职场文书