跳到内容

try-except-in-loop (PERF203)

源自 Perflint linter。

作用

检查在 forwhile 循环中使用 try-except 进行异常处理的情况。

为什么这不好?

无论是否引发异常,通过 try-except 块进行异常处理都会产生一定的性能开销。

为了优化您的代码,可以使用两种技术

  1. 重构您的代码,将整个循环放入 try-except 块中,而不是将每次迭代都包装在一个单独的 try-except 块中。
  2. 使用“先检查后执行”的惯用方法,尝试避免首先引发异常,从而避免使用 try-except 块的需要。

此规则仅对 Python 3.11 之前的版本强制执行,该版本引入了“零成本”异常处理。但是,请注意,即使在 Python 3.11 及更高版本上,重构代码以避免在紧密循环中进行异常处理也可以在某些情况下提供显着的加速,因为零成本异常处理仅在“快乐路径”中才是零成本,即在 try-except 块中没有引发异常。

与所有 perflint 规则一样,这仅旨在作为一种微优化。在许多情况下,它对性能的影响可以忽略不计。

示例

string_numbers: list[str] = ["1", "2", "three", "4", "5"]

# `try`/`except` that could be moved out of the loop:
int_numbers: list[int] = []
for num in string_numbers:
    try:
        int_numbers.append(int(num))
    except ValueError as e:
        print(f"Couldn't convert to integer: {e}")
        break

# `try`/`except` used when "look before you leap" idioms could be used:
number_names: dict[int, str] = {1: "one", 3: "three", 4: "four"}
for number in range(5):
    try:
        name = number_names[number]
    except KeyError:
        continue
    else:
        print(f"The name of {number} is {name}")

建议改为

string_numbers: list[str] = ["1", "2", "three", "4", "5"]

int_numbers: list[int] = []
try:
    for num in string_numbers:
        int_numbers.append(int(num))
except ValueError as e:
    print(f"Couldn't convert to integer: {e}")

number_names: dict[int, str] = {1: "one", 3: "three", 4: "four"}
for number in range(5):
    name = number_names.get(number)
    if name is not None:
        print(f"The name of {number} is {name}")

Options (选项)