“除Foo以外为条形图”导致“条形图”从范围中删除

时间:2018-10-24 09:50:09

标签: python python-3.x scoping

给出以下代码:

msg = "test"
try:
    "a"[1]
except IndexError as msg:
    print("Error happened")
print(msg)

有人可以解释为什么这会在Python 3中导致以下输出吗?

Error happened
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print(msg)
NameError: name 'msg' is not defined

3 个答案:

答案 0 :(得分:50)

msg在except子句中与第一行msg处于相同范围。

但是in Python 3 we have this new behavior too

  

使用as target分配了异常后,该异常将在以下位置清除   except子句的末尾。好像是

except E as N:
    foo
     

已翻译为

except E as N:
    try:
        foo
    finally:
        del N
     

这意味着必须将异常分配给其他名称   能够在except子句之后引用它。异常已清除   因为附加了追溯功能,它们形成了参考   循环使用堆栈框架,使该框架中的所有本地人保持活动状态   直到下一次垃圾回收发生为止。

因此,您在异常处理程序中“覆盖msg”,退出处理程序将删除该变量以清除回溯引用周期。

答案 1 :(得分:33)

是的,一旦引发异常并为msg分配了新的异常对象,原始对象就不再具有引用,因此将被删除。新的异常对象离开except块后也会被删除。

您可以通过覆盖对象的__del__方法和分配给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

答案 2 :(得分:7)

Exception块在块的末尾删除了捕获的变量,但是它们没有自己的作用域。因此,事件的顺序如下:

1)msg设置为本地范围内的某些字符串

2)msg设置为与1相同的本地范围内的IndexError对象

3)异常块结束后,msg从本地作用域中删除

4)msg不再在本地范围内定义,因此访问它的尝试失败