Python 中的 else详解

作者:hebedich 时间:2021-12-15 09:42:18 

我们都知道 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,else
0
投稿

猜你喜欢

  • 网页设计之文字的辨识度与可读性

    2007-10-26 16:19:00
  • 用Python批量把文件复制到另一个文件夹的实现方法

    2021-03-10 14:53:11
  • Python导入不同文件夹中文件的方法详解

    2022-01-22 09:30:08
  • 页面上存在多个FckEditor编辑器的验证方法

    2022-07-29 07:00:49
  • ASP 字符串转数字格式

    2009-08-19 17:18:00
  • Python应用之利用pyecharts画中国地图

    2023-05-27 16:45:40
  • OpenCV-Python使用cv2实现傅里叶变换

    2023-07-08 05:11:06
  • 基于Python实现人脸识别和焦点人物检测功能

    2021-03-09 10:27:45
  • 解决给dom元素绑定click等事件无效问题的方法

    2024-04-16 10:36:42
  • python实现高斯投影正反算方式

    2022-11-17 08:58:19
  • 详解如何用模块化的方式写vuejs

    2024-04-27 16:08:04
  • 解决MAC系统升级后虚拟机黑屏问题

    2022-08-10 05:37:53
  • Python PyQt4实现QQ抽屉效果

    2023-10-08 08:06:42
  • MySQL用户账户管理和权限管理深入讲解

    2024-01-20 22:42:59
  • Java并发编程数据库与缓存数据一致性方案解析

    2024-01-21 21:09:47
  • Django模板导入母版继承和自定义返回Html片段过程解析

    2023-06-16 21:13:38
  • pycharm重命名文件的方法步骤

    2021-10-21 23:16:42
  • SQL 中STUFF用法

    2024-01-25 01:14:30
  • 分享6 个值得收藏的 Python 代码

    2022-12-31 05:09:57
  • Python编写电话薄实现增删改查功能

    2021-07-14 21:28:18
  • asp之家 网络编程 m.aspxhome.com