try-except-in-loop (PERF203)
源自 Perflint linter。
作用
检查在 for
和 while
循环中使用 try
-except
进行异常处理的情况。
为什么这不好?
无论是否引发异常,通过 try
-except
块进行异常处理都会产生一定的性能开销。
为了优化您的代码,可以使用两种技术
- 重构您的代码,将整个循环放入
try
-except
块中,而不是将每次迭代都包装在一个单独的try
-except
块中。 - 使用“先检查后执行”的惯用方法,尝试避免首先引发异常,从而避免使用
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}")