在`except`子句中的名称绑定在子句之后删除

在`except`子句中的名称绑定在子句之后删除,第1张

在`except`子句中的名称绑定在子句之后删除

不,这不是错误。在Python
3文档中,针对

try
/
except
语句
明确定义了您所遇到的行为。还给出了此行为的原因:

当使用分配了异常后

as target
,该异常将在该
except
子句的末尾清除。好像

except E as N:   foo

被翻译成

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

这意味着必须将异常分配给其他名称,以便在

except
子句之后引用它。
清除异常是因为它们具有附加的回溯,它们与堆栈框架形成了一个参考循环,使该框架中的所有局部变量都保持活动状态,直到发生下一个垃圾回收为止

try
/
except
块范围之外声明名称无效的原因是因为您
exc
as
子句中使用了该名称。这就是Python删除的名称。

解决方法是在

as
子句中使用其他名称将异常绑定到,然后将全局变量分配给其他异常名称:

>>> exc_global = None>>> try:    1 / 0    text_template = "All fine!"except ZeroDivisionError as exc:    exc_global = exc    text_template = "Got exception: {exc.__class__.__name__}">>> print(text_template.format(exc=exc_global))Got exception: ZeroDivisionError

正如Anthony Sottile在评论中指出的,

try
/
except
代码的反汇编也明确支持文档中的上述声明:

>>> pre = """try:    1/0    text_template = "All fine!"except ZeroDivisionError as exc:    text_template = "Got exception: {exc.__class__.__name__}"""">>> from dis import dis>>> dis(pre)  20 SETUP_EXCEPT 16 (to 18)  32 LOAD_ConST    0 (1)   4 LOAD_ConST    1 (0)   6 BINARY_TRUE_DIVIDE   8 POP_TOP  4          10 LOAD_ConST    2 ('All fine!')  12 STORE_NAME    0 (text_template)  14 POP_BLOCK  16 JUMP_FORWARD 38 (to 56)  5     >>   18 DUP_TOP  20 LOAD_NAME     1 (ZeroDivisionError)  22 COMPARE_OP   10 (exception match)  24 POP_JUMP_IF_FALSE       54  26 POP_TOP  28 STORE_NAME    2 (exc)  30 POP_TOP  32 SETUP_FINALLY10 (to 44)  6          34 LOAD_ConST    3 ('Got exception: {exc.__class__.__name__}')  36 STORE_NAME    0 (text_template)  38 POP_BLOCK  40 POP_EXCEPT  42 LOAD_ConST    4 (None)        >>   44 LOAD_ConST    4 (None)  46 STORE_NAME    2 (exc)  48 DELETE_NAME   2 (exc)  50 END_FINALLY  52 JUMP_FORWARD  2 (to 56)        >>   54 END_FINALLY        >>   56 LOAD_ConST    4 (None)  58 RETURN_VALUE


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5654980.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存