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执行等待程序直到第二天零点的方法
Apr 23 Python
python返回昨天日期的方法
May 13 Python
Python中的模块导入和读取键盘输入的方法
Oct 16 Python
非递归的输出1-N的全排列实例(推荐)
Apr 11 Python
Python之reload流程实例代码解析
Jan 29 Python
python 常用的基础函数
Jul 10 Python
PyCharm的设置方法和第一个Python程序的建立
Jan 16 Python
Python CSV文件模块的使用案例分析
Dec 21 Python
Python3+selenium实现cookie免密登录的示例代码
Mar 18 Python
Python装饰器实现方法及应用场景详解
Mar 26 Python
Python加载数据的5种不同方式(收藏)
Nov 13 Python
Python将QQ聊天记录生成词云的示例代码
Feb 10 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 会话(session 时间设定)使用入门代码
2008/06/05 PHP
PHP中echo,print_r与var_dump区别分析
2014/09/29 PHP
购物车实现的几种方式优缺点对比
2018/05/02 PHP
才发现的超链接js导致网页中GIF动画停止的解决方法
2007/11/02 Javascript
JavaScript Date对象使用总结
2009/05/14 Javascript
jquery sortable的拖动方法示例详解
2014/01/16 Javascript
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
jQuery中serializeArray()与serialize()的区别实例分析
2015/12/09 Javascript
Sea.JS知识总结
2016/05/05 Javascript
JavaScript寄生组合式继承原理与用法分析
2019/01/11 Javascript
vue鼠标悬停事件实例详解
2019/04/01 Javascript
vue实现树形结构样式和功能的实例代码
2019/10/15 Javascript
[36:22]VP vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
使用Python的Tornado框架实现一个简单的WebQQ机器人
2015/04/24 Python
Python整数与Numpy数据溢出问题解决
2019/09/11 Python
tensorflow 实现打印pb模型的所有节点
2020/01/23 Python
Django 实现将图片转为Base64,然后使用json传输
2020/03/27 Python
Tensorflow使用Anaconda、pycharm安装记录
2020/07/29 Python
最新Python idle下载、安装与使用教程图文详解
2020/11/28 Python
Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)
2020/12/14 Python
HTML5如何实现元素拖拽
2016/03/11 HTML / CSS
查找廉价航班和发现新目的地:Kiwi.com
2019/02/25 全球购物
迪士尼英国官方商店:shopDisney UK
2019/09/21 全球购物
火山动力Java笔试题
2014/06/26 面试题
英文商务邀请信
2014/01/22 职场文书
先进事迹报告会感言
2014/01/24 职场文书
四风存在的原因分析
2014/02/11 职场文书
2014年乡镇植树节活动方案
2014/02/28 职场文书
房地产活动策划方案
2014/05/14 职场文书
教师师德师风整改措施
2014/10/24 职场文书
群众路线教育实践活动学习心得体会
2014/10/30 职场文书
2014年采购工作总结
2014/11/20 职场文书
2015年反腐倡廉工作总结
2015/05/14 职场文书
JS数组的常用方法整理
2021/03/31 Javascript
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
详细分析PHP7与PHP5区别
2021/06/26 PHP