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 list转dict示例分享
Jan 28 Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 Python
Python的__builtin__模块中的一些要点知识
May 02 Python
rabbitmq(中间消息代理)在python中的使用详解
Dec 14 Python
Python基于Floyd算法求解最短路径距离问题实例详解
May 16 Python
Python numpy实现二维数组和一维数组拼接的方法
Jun 05 Python
利用Python如何实现一个小说网站雏形
Nov 23 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
Apr 15 Python
Django处理多用户类型的方法介绍
May 18 Python
softmax及python实现过程解析
Sep 30 Python
python实现猜单词游戏
May 22 Python
如何利用python发送邮件
Sep 26 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
php防注入及开发安全详细解析
2013/08/09 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
2014/12/15 PHP
PHP获取Exif缩略图的方法
2015/07/13 PHP
PHP面向对象五大原则之里氏替换原则(LSP)详解
2018/04/08 PHP
jQuery 全选效果实现代码
2009/03/23 Javascript
javascript 变量作用域 代码分析
2009/06/26 Javascript
比较详细的关于javascript 解析json的代码
2009/12/16 Javascript
jquery.jstree 增加节点的双击事件代码
2010/07/27 Javascript
window.open 以post方式传递参数示例代码
2014/02/27 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
js格式化输入框内金额、银行卡号
2016/02/01 Javascript
JavaScript中的Object对象学习教程
2016/05/20 Javascript
基于JS实现密码框(password)中显示文字提示功能代码
2016/05/27 Javascript
URL的参数中有加号传值变为空格的问题(URL特殊字符)
2016/11/04 Javascript
JS中使用正则表达式g模式和非g模式的区别
2017/04/01 Javascript
Node使用Sequlize连接Mysql报错:Access denied for user ‘xxx’@‘localhost’
2018/01/03 Javascript
vue2.0实现音乐/视频播放进度条组件
2018/06/06 Javascript
小程序实现多列选择器
2019/02/15 Javascript
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
浅谈MySQL中的触发器
2015/05/05 Python
python 多线程实现检测服务器在线情况
2015/11/25 Python
Python 内置函数进制转换的用法(十进制转二进制、八进制、十六进制)
2018/04/30 Python
python skimage 连通性区域检测方法
2018/06/21 Python
用python生成1000个txt文件的方法
2018/10/25 Python
Python3数字求和的实例
2019/02/19 Python
浅析python redis的连接及相关操作
2019/11/07 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
python求前n个阶乘的和实例
2020/04/02 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
化验室技术员岗位职责
2013/12/24 职场文书
创业计划书怎样才能打动风投
2014/01/01 职场文书
小学生竞选班长演讲稿
2014/04/24 职场文书
关于运动会广播稿50字
2014/10/18 职场文书
黑白记忆观后感
2015/06/18 职场文书
解决使用了nginx获取IP地址都是127.0.0.1 的问题
2021/09/25 Servers