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遍历指定文件及文件夹的方法
May 09 Python
讲解Python中运算符使用时的优先级
May 14 Python
Python 比较两个数组的元素的异同方法
Aug 17 Python
python线程池(threadpool)模块使用笔记详解
Nov 17 Python
Python基于Flask框架配置依赖包信息的项目迁移部署
Mar 02 Python
Python数据分析matplotlib设置多个子图的间距方法
Aug 03 Python
Python paramiko模块使用解析(实现ssh)
Aug 30 Python
Python StringIO如何在内存中读写str
Jan 07 Python
pycharm 更改创建文件默认路径的操作
Feb 15 Python
keras中的backend.clip用法
May 22 Python
Python中内建模块collections如何使用
May 27 Python
PyQt5 显示超清高分辨率图片的方法
Apr 11 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
Windows Apache2.2.11及Php5.2.9-1的安装与配置方法
2009/06/08 PHP
使用PHP遍历文件夹与子目录的函数代码
2011/09/26 PHP
关于PHP结束标签的使用细节探讨及联想
2013/03/04 PHP
ThinkPHP中的create方法与自动令牌验证实例教程
2014/08/22 PHP
php第一次无法获取cookie问题处理
2014/12/15 PHP
详解Yii2 rules 的验证规则
2016/12/02 PHP
thinkPHP和onethink微信支付插件分享
2019/08/11 PHP
JS获取后台Cookies值的小例子
2013/03/04 Javascript
js导航菜单(自写)简单大方
2013/03/28 Javascript
弹出窗口并且此窗口带有半透明的遮罩层效果
2014/03/13 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
javascript和jquery实现用户登录验证
2016/05/04 Javascript
JS中常用的输出方式(五种)
2016/06/12 Javascript
BootStrap网页中代码显示用法详解
2016/10/21 Javascript
Bootstrap源码解读标签、徽章、缩略图和警示框(8)
2016/12/26 Javascript
jQuery validate 验证radio实例
2017/03/01 Javascript
jQuery Chosen通用初始化
2017/03/07 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
2019/07/29 Javascript
微信小程序实现单个卡片左滑显示按钮并防止上下滑动干扰功能
2019/12/06 Javascript
JS实现简单日历特效
2020/01/03 Javascript
微信小程序学习总结(五)常见问题实例小结
2020/06/04 Javascript
Python对象体系深入分析
2014/10/28 Python
pycharm重置设置,恢复默认设置的方法
2018/10/22 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
Pytorch中index_select() 函数的实现理解
2019/11/19 Python
Python绘图实现显示中文
2019/12/04 Python
Opencv 图片的OCR识别的实战示例
2021/03/02 Python
Farfetch中文官网:奢侈品牌时尚购物平台
2020/03/15 全球购物
澳大利亚厨房和家用电器购物网站:Bing Lee
2021/01/11 全球购物
军训 自我鉴定
2014/02/03 职场文书
商场消防演习方案
2014/02/12 职场文书
小学生读书活动总结
2014/06/30 职场文书
代收款委托书范本
2014/10/01 职场文书
党员自我评价范文2015
2015/03/03 职场文书
2016年小学“公民道德宣传日”活动总结
2016/04/01 职场文书
2016年幼儿园万圣节活动总结
2016/04/05 职场文书