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调用shell的方法
Nov 20 Python
python创建和删除目录的方法
Apr 29 Python
Python实现将DOC文档转换为PDF的方法
Jul 25 Python
详解Python中的Descriptor描述符类
Jun 14 Python
python实现Adapter模式实例代码
Feb 09 Python
python中pylint使用方法(pylint代码检查)
Apr 06 Python
解决python中无法自动补全代码的问题
Dec 04 Python
Python使用requests提交HTTP表单的方法
Dec 26 Python
OpenCV+Python识别车牌和字符分割的实现
Jan 31 Python
Python基于Tkinter编写crc校验工具
May 06 Python
Python Dict找出value大于某值或key大于某值的所有项方式
Jun 05 Python
python ssh 执行shell命令的示例
Sep 29 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类的静态(static)方法和静态(static)变量使用介绍
2012/02/19 PHP
PHP和Mysql中转UTF8编码问题汇总
2015/10/10 PHP
Extjs4.0设置Ext.data.Store传参的请求方式(默认为GET)
2013/04/02 Javascript
js事件监听机制(事件捕获)总结
2014/08/08 Javascript
jQuery对象与DOM对象之间的相互转换
2015/03/03 Javascript
jQuery向webApi提交post json数据
2017/01/16 Javascript
JavaScript中object和Object的区别(详解)
2017/02/27 Javascript
微信小程序页面开发注意事项整理
2017/05/18 Javascript
JavaScript编程设计模式之观察者模式(Observer Pattern)实例详解
2017/10/25 Javascript
JS实现的判断方法、变量是否存在功能示例
2020/03/28 Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
微信小程序云开发如何实现数据库自动备份实现
2019/08/16 Javascript
Vue根据条件添加click事件的方式
2019/11/09 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
Echarts.js无法引入问题解决方案
2020/10/30 Javascript
[59:35]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第一场 1月8日
2021/03/11 DOTA
python函数局部变量用法实例分析
2015/08/04 Python
python使用递归的方式建立二叉树
2019/07/03 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
python opencv图片编码为h264文件的实例
2019/12/12 Python
python的slice notation的特殊用法详解
2019/12/27 Python
Python连接HDFS实现文件上传下载及Pandas转换文本文件到CSV操作
2020/06/06 Python
python里的单引号和双引号的有什么作用
2020/06/17 Python
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
采用怎样的方法保证数据的完整性
2013/12/02 面试题
设计模式的基本要素是什么
2014/04/21 面试题
我与祖国共奋进演讲稿
2014/09/13 职场文书
教师个人工作总结范文2014
2014/11/10 职场文书
工伤劳动仲裁代理词
2015/05/25 职场文书
2015国庆节宣传语
2015/07/14 职场文书
教师师德工作总结2015
2015/07/22 职场文书
幼儿园小朋友毕业感言
2015/07/30 职场文书
体育委员竞选稿
2015/11/21 职场文书
2016年“我们的节日·重阳节”主题活动总结
2016/04/01 职场文书
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle
彩虹社八名人气艺人全新周边限时推出,性转女装男装一次拥有!
2022/04/01 日漫