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的SimpleHTTPServer源码来解析socket通信
Jun 27 Python
Python 读写文件和file对象的方法(推荐)
Sep 12 Python
教大家玩转Python字符串处理的七种技巧
Mar 31 Python
python retrying模块的使用方法详解
Sep 25 Python
python创建ArcGIS shape文件的实现
Dec 06 Python
Django之富文本(获取内容,设置内容方式)
May 21 Python
基于Python第三方插件实现西游记章节标注汉语拼音的方法
May 22 Python
Python如何绘制日历图和热力图
Aug 07 Python
详解Python高阶函数
Aug 15 Python
python使用requests库爬取拉勾网招聘信息的实现
Nov 20 Python
python操作xlsx格式文件并读取
Jun 02 Python
Python pandas之求和运算和非空值个数统计
Aug 07 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跨时区(UTC时间)应用解决方案
2013/01/11 PHP
使用phpexcel类实现excel导入mysql数据库功能(实例代码)
2016/05/12 PHP
jQuery 选择表格(table)里的行和列及改变简单样式
2012/12/15 Javascript
文档对象模型DOM通俗讲解
2013/11/01 Javascript
JavaScript中的bold()方法使用详解
2015/06/08 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
2015/10/04 Javascript
JavaScript笔记之数据属性和存储器属性
2016/03/31 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
2016/07/26 Javascript
js验证手机号、密码、短信验证码代码工具类
2020/06/24 Javascript
微信小程序 template模板详解及实例代码
2017/03/09 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
bootstrap table实现点击翻页功能 可记录上下页选中的行
2017/09/28 Javascript
每个 JavaScript 工程师都应懂的33个概念
2018/10/22 Javascript
layui字体图标 loading图标静止不旋转的解决方法
2019/09/23 Javascript
layui扩展上传组件模拟进度条的方法
2019/09/23 Javascript
python获取外网IP并发邮件的实现方法
2017/10/01 Python
python中获得当前目录和上级目录的实现方法
2017/10/12 Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
2018/12/18 Python
如何使用Python标准库进行性能测试
2019/06/25 Python
Python使用uuid库生成唯一标识ID
2020/02/12 Python
python 项目目录结构设置
2020/02/14 Python
Timberland美国官网:全球领先的户外品牌
2016/08/15 全球购物
世界上最大的售后摩托车零配件超市:J&P Cycles
2017/12/08 全球购物
alice McCALL官网:澳大利亚时尚品牌
2020/11/16 全球购物
如何拷贝一整个Java对象,包括它的状态
2013/12/27 面试题
2015年上半年信访工作总结
2015/03/30 职场文书
2015年工程师工作总结
2015/04/30 职场文书
公司2015年终工作总结
2015/05/26 职场文书
2015年食品安全宣传周活动总结
2015/07/09 职场文书
高二英语教学反思
2016/03/03 职场文书
2019开业庆典剪彩仪式主持词!
2019/07/22 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书
Python中基础数据类型 set集合知识点总结
2021/08/02 Python
详细聊一聊mysql的树形结构存储以及查询
2022/04/05 MySQL
2022年显卡天梯图(6月更新)
2022/06/17 数码科技
win10电脑双屏显示一个黑屏怎么办?win10电脑双屏显示一个黑屏解决方法
2022/07/15 数码科技