Python 与 try-except-finally 中的 return 值混淆
Python confusion with return value in try-except-finally
这是我的一段代码:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
return num
finally:
num += 1
a = main()
print(a)
returning 值是 1
而不是 2
,这对我来说意义不大。
我认为它会 return 2 因为 finally 应该在 return 值之前执行。
谁能帮我理解一下?
finally
块 在 return 计算值之前执行,但是 return 值已经被计算。
return num
计算 num
,得到 1
,然后 finally
块开始。 finally
块递增 num
,但是 return 值已经计算过,所以这无关紧要。最后,之前计算的 1
是 returned.
您 运行 了解标识符和值之间的区别。 num += 1
正在创建一个新的 int
对象并分配 num
标识符以指向它。它不会更改标识符已指向的 int
对象。 (对于小值,int
对象被缓存,但这是一个实现细节)
您可以在下面的代码中看到与确实改变对象的操作的区别:
def y():
l = []
try:
raise Exception
except Exception:
print("except")
l.append(1)
return l
finally:
print("finally")
l.append(2)
print(y())
# except
# finally
# [1, 2]
那是因为你在 except 块中 returning
使用 return 字将结束此函数中的代码执行。
为了避免它,你可以这样写:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
finally:
num += 1
return num
a = main()
print(a)
执行了finally
(这在documentation中有明确定义),但是当你return一个不可变对象时,修改是看不见的,因为您的 returned 名称现在是不同范围的一部分。
对于可变对象(例如列表),这会像您期望的那样工作:
def main():
lst = [0]
try:
raise Exception('This is the error message.')
except Exception:
lst[0] += 1
return lst
finally:
lst[0] += 1
a = main()
print(a)
输出:[2]
这是我的一段代码:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
return num
finally:
num += 1
a = main()
print(a)
returning 值是 1
而不是 2
,这对我来说意义不大。
我认为它会 return 2 因为 finally 应该在 return 值之前执行。
谁能帮我理解一下?
finally
块 在 return 计算值之前执行,但是 return 值已经被计算。
return num
计算 num
,得到 1
,然后 finally
块开始。 finally
块递增 num
,但是 return 值已经计算过,所以这无关紧要。最后,之前计算的 1
是 returned.
您 运行 了解标识符和值之间的区别。 num += 1
正在创建一个新的 int
对象并分配 num
标识符以指向它。它不会更改标识符已指向的 int
对象。 (对于小值,int
对象被缓存,但这是一个实现细节)
您可以在下面的代码中看到与确实改变对象的操作的区别:
def y():
l = []
try:
raise Exception
except Exception:
print("except")
l.append(1)
return l
finally:
print("finally")
l.append(2)
print(y())
# except
# finally
# [1, 2]
那是因为你在 except 块中 returning 使用 return 字将结束此函数中的代码执行。 为了避免它,你可以这样写:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
finally:
num += 1
return num
a = main()
print(a)
执行了finally
(这在documentation中有明确定义),但是当你return一个不可变对象时,修改是看不见的,因为您的 returned 名称现在是不同范围的一部分。
对于可变对象(例如列表),这会像您期望的那样工作:
def main():
lst = [0]
try:
raise Exception('This is the error message.')
except Exception:
lst[0] += 1
return lst
finally:
lst[0] += 1
a = main()
print(a)
输出:[2]