>>> from env_helper import info; info()
页面更新时间: 2024-01-06 09:15:03
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

3.5. 使用 else 子句简化循环(异常处理)

有其他编程语言经验的程序员接触到Python时,对于它无所不在的 else 往往感到非常 惊讶。 在Python中,不仅分支语句有 else 子句,而且循环语句也有,甚至连异常处理也有。 首先来看者循环语句中的 else , 看看它们的语法。

while_stmt :: = "while" expression ":" suite

["else" ":"suite]

for_stmt :: = "for" target_list "in" expression_list " :", suite

["else" ":" suite]

从语法定义中可以看到如果没有 ["else" ":" suite] 这一块,Python的循环语句跟大多数语言并无二致。 要谈 else 子句,必须先从Python从其他语言中借鉴的语义相同的 break 语句说 起, 因为 else 子句提供了隐含的对循环是否由 break 语句引发循环结束的判断。

先来看一个没有使用 else 子句的例子:

>>> def print_p(n):
>>>     for i in range(2, n):
>>>         found = True
>>>         for j in range(2, i):
>>>             if i % j == 0:
>>>                 found = False
>>>                 break
>>>         if found:
>>>             print ("%d is a prime number"%i)
>>> print_p(20)
2 is a prime number
3 is a prime number
5 is a prime number
7 is a prime number
11 is a prime number
13 is a prime number
17 is a prime number
19 is a prime number

这是一个査找素数的简单实现,可以看到我们借助了一个标志量 found 来判断是循环结束是不是由 break 语句引起的。

如果对 else 善加利用,代码可以简洁得多。来看下面的具体 实现:

>>> def print_prime2 (n) :
>>>     for i in range(2, n):
>>>         for j in range(2, i):
>>>             if i % j == 0:
>>>                 break
>>>         else:
>>>             print ("%d is a prime number1"%i)
>>> print_prime2(20)
2 is a prime number1
3 is a prime number1
5 is a prime number1
7 is a prime number1
11 is a prime number1
13 is a prime number1
17 is a prime number1
19 is a prime number1

当循环“自然”终结(循环条件为假)时 else 从句会被执行一次, 而当循环是由 break 语句中断时, else 子句就不被执行。 与 for 语句相似, while 语句中的 else 子句的语意是一样 的: else 块在循环正常结朿和循环条件不成立时被执行。

与C/C++等较为“老土”的语言相比, else 子句使程序员的生产力和代码的可读性都得到了提髙, 所以建议大家多使用 else ,让程序变得更加Pythcmic。

在Python的异常处理中,也提供了 else 子句语法。 这颗“语法糖”的意义跟循环语句中的 else 是相似的: try 块没有拋出任何异常时,执行 else 块。 按惯例先看一下如下语 法定义:

try_stmt ::= tryl_stmt | try2_stmt tryl_stmt ::= "try" ":" suite

("except" [expression [ ("as" | ",") target]]":" suite) +["else" ":" suite] ["finally" ":" suite]

try2_stmt ::= "try" ":" suite

"finally" ":" suite

tryl_stmt的定义中可以看到,Python的异常处理中有一种try-except-else-finally形式。 下面的例子是把数据写入文件中。

>>> def save(db, obj):
>>>     try:
>>>         # save attrl
>>>         db.execute('a sql stmt', obj.attr1)
>>>         # save attr2
>>>         db.execute('another sql stmt', obj.attr2)
>>>     except DBError:
>>>         db.rollback()
>>>     else:
>>>         db.commit ()

如果没有 else子 句,就像前文中关于循环的例子一样,需要引人一个标志变量。

>>> def save(db, obj):
>>>     some_error_occurred= False
>>>     try:
>>>         # save attrl
>>>         db.execute ( ' a sql stmt', obj.attr1)
>>>         # save attr2
>>>         db.execute ('another sql stmt', obj.attr2)
>>>     except DBError:
>>>         db.rollback()
>>>         some_error_occurred = True
>>>     if not some_error_occurred:
>>>         db.commit ()

这样代码就变得复杂了。在Python中还有不少语法都是致力于让程序员可以编写更加 简明、更接近自然语言语义的代码。