Python &引用;除Foo as bar外“;原因“;酒吧;从范围中删除
给定以下代码:Python &引用;除Foo as bar外“;原因“;酒吧;从范围中删除,python,python-3.x,scoping,Python,Python 3.x,Scoping,给定以下代码: msg = "test" try: "a"[1] except IndexError as msg: print("Error happened") print(msg) 有人能解释一下为什么在Python3中会出现以下输出吗 发生错误 回溯(最近一次呼叫最后一次): 文件“test.py”,第6行,在 打印(msg) NameError:未定义名称“msg” 是,一旦引发异常并为新异常对象分配了msg,原始对象就不再有引用,因此被删除。新的异常对象在离开exc
msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)
有人能解释一下为什么在Python3中会出现以下输出吗
发生错误
回溯(最近一次呼叫最后一次):
文件“test.py”,第6行,在
打印(msg)
NameError:未定义名称“msg”
是,一旦引发异常并为新异常对象分配了msg
,原始对象就不再有引用,因此被删除。新的异常对象在离开except
块时也会被删除
您可以通过覆盖对象的方法和分配给msg
的异常来验证它:
class A:
def __del__(self):
print('object deleted')
class E(Exception):
def __del__(self):
print('exception deleted')
msg = A()
try:
raise E()
except E as msg:
print("Error happened")
这将产生:
object deleted
Error happened
exception deleted
NameError: name 'msg' is not defined
except子句中的msg
与第一行的msg
在同一范围内
但是:
当使用作为目标分配异常时,将在
except子句的结尾。这就好像
except E as N:
foo
翻译成
except E as N:
try:
foo
finally:
del N
这意味着必须将该异常分配给要处理的其他名称
可以在except子句之后引用它。例外情况已清除
因为有了回溯,它们就形成了一个引用
循环堆栈帧,使该帧中的所有局部变量保持活动状态
直到下一次垃圾回收发生
因此,您在异常处理程序中“overwritemsg
”,退出该处理程序将删除变量以清除回溯引用循环。异常块删除块末尾捕获的变量,但它们没有自己的作用域。因此,事件的顺序如下:
1) msg
设置为本地范围内的某个字符串
2) msg
被设置为与1在同一本地范围内的索引器对象
3) 异常块结束时,从本地作用域中删除msg
4) msg
不再在本地作用域中定义,因此访问它的尝试失败这特别回答了在之后如何以及为什么删除先前的msg
的问题,除了:
,包括对文档的引用,因此我认为它应该是可接受的答案。@LightnessRacesinOrbit是的,这确实很奇怪。我的意思是:如果你想要一个新的作用域,那么就创建一个新的作用域,不要终止对第一个msg
的引用。如果您不想要一个新的作用域,那么为什么要终止异常引用呢?它一点也不不不可靠。通过使用除了。。。作为msg
您正在将msg
绑定到异常,该异常将删除对原始对象的所有引用。相反,如果<代码>除了。。。因为使用了m
,所以不会产生任何问题,因为原始绑定msg
没有在except块中修改。@Shamtam正如Giacomo解释的那样,它肯定是不可靠的。Python的工作方式是在现有范围内重新绑定msg
。但是msg
的范围存在于try
块之外(如果没有引发异常,则将继续存在)。运行时条件决定变量(应该是静态的)的范围这一事实是系统类型的CRASSubversion。由于Python是动态类型化的,这当然是可行的,但它仍然很奇怪。而且,Python2的处理方式完全不同,正如预期的那样。@Shamtam“这就是Python的工作方式”:这当然是真的。没有人否认这一点。但这并不意味着人们不应该认为Python是不可靠的。“其他流行语言”中的作用域规则允许使用这些语言的程序员避免在到达except块(或类似块)之前跟踪所用名称的心理负担,从而能够避免在块中使用现有名称;解释器或编译器为它们执行此操作。原因msg
在末尾被删除,除了
块与作用域无关。他们希望清除在Python 3中添加\uuu traceback\uuu
属性所创建的引用循环。看见这确实令人困惑,有一个强有力的论据认为Python应该停止尝试支持在关闭GC的情况下运行,但这不是范围问题。