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插入排序算法的实现代码
Nov 21 Python
Python使用matplotlib实现在坐标系中画一个矩形的方法
May 20 Python
Windows下Python使用Pandas模块操作Excel文件的教程
May 31 Python
python os用法总结
Jun 08 Python
Python读写文件基础知识点
Jun 10 Python
Python读取xlsx文件的实现方法
Jul 04 Python
python 的 openpyxl模块 读取 Excel文件的方法
Sep 09 Python
使用TensorFlow对图像进行随机旋转的实现示例
Jan 20 Python
python 实现多维数组(array)排序
Feb 28 Python
通过实例了解python__slots__使用方法
Sep 14 Python
python对批量WAV音频进行等长分割的方法实现
Sep 25 Python
matplotlib事件处理基础(事件绑定、事件属性)
Feb 03 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
收集的DedeCMS一些使用经验
2007/03/17 PHP
PHP中使用break跳出多重循环代码实例
2015/01/21 PHP
Smarty中的注释和截断功能介绍
2015/04/09 PHP
全面解读PHP的人气开发框架Laravel
2015/10/15 PHP
PHP简单实现文本计数器的方法
2016/04/28 PHP
Yii2框架可逆加密简单实现方法
2017/08/25 PHP
php测试kafka项目示例
2020/02/06 PHP
JavaScript 编程引入命名空间的方法
2007/06/29 Javascript
javascript获取网页中指定节点的父节点、子节点的方法小结
2013/04/24 Javascript
Javascript 读取操作Sql中的Xml字段
2014/10/09 Javascript
jQuery实现字符串按指定长度加入特定内容的方法
2015/03/11 Javascript
ECMAScript6中Map/WeakMap详解
2015/06/12 Javascript
JavaScript运动减速效果实例分析
2015/08/04 Javascript
谈谈对offsetleft兼容性的理解
2015/11/11 Javascript
浅析AngularJS中的指令
2016/03/20 Javascript
bootstrap-wysiwyg结合ajax实现图片上传实时刷新功能
2016/05/27 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
2016/11/22 Javascript
jquery submit()不能提交表单的解决方法
2017/04/24 jQuery
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
解决修复npm安装全局模块权限的问题
2018/05/17 Javascript
webpack的CSS加载器的使用
2018/09/11 Javascript
微信小程序iOS下拉白屏晃动问题解决方案
2019/10/12 Javascript
Python文本相似性计算之编辑距离详解
2016/11/28 Python
python递归函数绘制分形树的方法
2018/06/22 Python
Python调用接口合并Excel表代码实例
2020/03/31 Python
美国伊甸园兄弟种子公司:Eden Brothers
2018/07/01 全球购物
美国家居装饰店:Pier 1
2019/09/04 全球购物
恒华伟业笔试面试题
2015/02/26 面试题
交通事故赔偿协议书
2014/04/15 职场文书
语文高效课堂实施方案
2014/05/03 职场文书
幼儿园2014年度工作总结
2014/11/10 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
护士2015年终工作总结
2015/04/29 职场文书
社区艾滋病宣传活动总结
2015/05/07 职场文书
教师节表彰会主持词
2015/07/06 职场文书
2015年大学迎新晚会总结
2015/07/16 职场文书