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基于Socket实现的简单聊天程序示例
Aug 05 Python
python中从str中提取元素到list以及将list转换为str的方法
Jun 26 Python
对pandas的层次索引与取值的新方法详解
Nov 06 Python
Python玩转Excel的读写改实例
Feb 22 Python
Python学习笔记之图片人脸检测识别实例教程
Mar 06 Python
Python使用Pickle模块进行数据保存和读取的讲解
Apr 09 Python
python读写csv文件实例代码
Jul 05 Python
Python 最强编辑器详细使用指南(PyCharm )
Sep 16 Python
python实现计算器功能
Oct 31 Python
python中property和setter装饰器用法
Dec 19 Python
使用OpenCV获取图像某点的颜色值,并设置某点的颜色
Jun 02 Python
Pandas 数据编码的十种方法
Apr 20 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设计模式 Interpreter(解释器模式)
2011/06/26 PHP
PHP 第二节 数据类型之数值型
2012/04/28 PHP
php中利用str_pad函数生成数字递增形式的产品编号
2013/09/30 PHP
php根据日期或时间戳获取星座信息和生肖等信息
2015/10/20 PHP
php中array_column函数简单实现方法
2016/07/11 PHP
laravel清除视图缓存的代码
2019/10/23 PHP
Laravel框架数据库迁移操作实例详解
2020/04/06 PHP
javascript 图片上传预览-兼容标准
2009/06/01 Javascript
JQuery筛选器全系列介绍
2013/08/27 Javascript
浅析Javascript使用include/require
2013/11/13 Javascript
javascript验证身份证号
2015/03/03 Javascript
分享我的jquery实现下拉菜单心的
2015/11/29 Javascript
详解iframe与frame的区别
2016/01/13 Javascript
原生态js,鼠标按下后,经过了那些单元格的简单实例
2016/08/11 Javascript
JS实现简单的二元方程计算器功能示例
2017/01/03 Javascript
VUE元素的隐藏和显示(v-show指令)
2017/06/23 Javascript
JS实现提交表单前的数字及邮箱校检功能
2017/11/13 Javascript
js时间戳与日期格式之间相互转换
2017/12/11 Javascript
JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
2018/07/27 Javascript
vue.js编译时给生成的文件增加版本号
2018/09/17 Javascript
elementUI中Table表格问题的解决方法
2018/12/04 Javascript
Vue 使用计时器实现跑马灯效果的实例代码
2019/07/11 Javascript
详解Element-UI中上传的文件前端处理
2019/08/07 Javascript
layui动态绑定事件的方法
2019/09/20 Javascript
微信小程序实现吸顶效果
2020/01/08 Javascript
老生常谈python函数参数的区别(必看篇)
2017/05/29 Python
TensorFlow 合并/连接数组的方法
2018/07/27 Python
Django实现分页显示效果
2019/10/31 Python
10分钟入门CSS3 Animation
2018/12/25 HTML / CSS
德国拖鞋网站:German Slippers
2019/11/08 全球购物
护理专科毕业生自荐书范文
2014/02/19 职场文书
大学生就业自荐书
2014/06/16 职场文书
个人作风建设剖析材料
2014/10/11 职场文书
分居协议书范本(律师见证版)
2014/11/26 职场文书
2015年幼儿园安全工作总结
2015/05/12 职场文书
欢送会主持词
2015/07/01 职场文书