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 15 Python
Python聊天室实例程序分享
Jan 05 Python
python win32 简单操作方法
May 25 Python
python实现员工管理系统
Jan 11 Python
Python实现二维数组输出为图片
Apr 03 Python
对Python 窗体(tkinter)树状数据(Treeview)详解
Oct 11 Python
python 通过SSHTunnelForwarder隧道连接redis的方法
Feb 19 Python
Python读写文件基础知识点
Jun 10 Python
TensorFLow 数学运算的示例代码
Apr 21 Python
pytorch实现查看当前学习率
Jun 24 Python
python压包的概念及实例详解
Feb 17 Python
Pytorch中TensorBoard及torchsummary的使用详解
May 12 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使用array_multisort对多个数组或多维数组进行排序
2014/12/16 PHP
php框架知识点的整理和补充
2021/03/01 PHP
IE6背景图片不缓存问题解决方案及图片使用策略多个方法小结
2012/05/14 Javascript
JS实现网页标题栏显示当前时间和日期的完整代码
2015/11/02 Javascript
Avalon中文长字符截取、关键字符隐藏、自定义过滤器
2016/05/18 Javascript
AngularJS入门教程之Helloworld示例
2016/12/25 Javascript
validationEngine 表单验证插件使用实例代码
2017/06/15 Javascript
JS实现身份证输入框的输入效果
2017/08/21 Javascript
vue实现动态显示与隐藏底部导航的方法分析
2019/02/11 Javascript
jQuery实现轮播图源码
2019/10/23 jQuery
javascript实现点击星星小游戏
2019/12/24 Javascript
AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略
2020/03/13 Javascript
vue-cli+webpack项目打包到服务器后,ttf字体找不到的解决操作
2020/08/28 Javascript
JavaScript判断数据类型有几种方法及区别介绍
2020/09/02 Javascript
django之session与分页(实例讲解)
2017/11/13 Python
linux环境下的python安装过程图解(含setuptools)
2017/11/22 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
django多对多表的创建,级联删除及手动创建第三张表
2019/07/25 Python
python程序 创建多线程过程详解
2019/09/23 Python
浅谈对pytroch中torch.autograd.backward的思考
2019/12/27 Python
详解python tkinter模块安装过程
2020/01/06 Python
python 使用elasticsearch 实现翻页的三种方式
2020/07/31 Python
python开发入门——set的使用
2020/09/03 Python
python 基于opencv实现高斯平滑
2020/12/18 Python
python之随机数函数的实现示例
2020/12/30 Python
CSS3的文字阴影—text-shadow的使用方法
2012/12/25 HTML / CSS
英国经典球衣网站:Classic Football Shirts
2017/05/20 全球购物
简述DNS进行域名解析的过程
2013/12/02 面试题
小区门卫工作职责
2013/12/14 职场文书
奥利奥广告词
2014/03/20 职场文书
财务部会计岗位职责
2015/02/03 职场文书
创建文明城市倡议书
2015/04/28 职场文书
优秀班干部主要事迹材料
2015/11/04 职场文书
创业计划书之暑假培训班
2019/11/09 职场文书
JavaScript 实现页面滚动动画
2021/04/24 Javascript
JavaScript事件的委托(代理)的用法示例详解
2022/02/18 Javascript