前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >有趣的 Python 特性 1 | 是谁吃掉了我的外部变量?

有趣的 Python 特性 1 | 是谁吃掉了我的外部变量?

作者头像
编程文青李狗蛋
发布2019-11-07 16:41:05
4470
发布2019-11-07 16:41:05
举报
文章被收录于专栏:编程文青李狗蛋
本文字数:1240 字 阅读本文大概需要:4 分钟

写在之前

Python 提供了很多让使用者觉得舒服至极的功能特性,但是随着不断的深入学习和使用 Python,我发现其中存在着许多玄学的输出与之前预想的结果大相径庭,这个对于初学者来说难以理解,但是在理解它们以后又会觉得是这么的有意思,所以我准备了这个「有趣的 Python 特性」系列,写一些我碰到或看到的一些你所不知道的「奇葩」,这里面会涉及到在 Python2 和 Python3 中的异同,希望大家能从学习的过程中体会到真正的乐趣。

被吃掉的外部变量

首先我们先来看这么一个例子:

代码语言:javascript
复制
e = 429

try:
    raise Exception()
except Exception as e:
    pass

print(e)

PS:except Exception as e 可以捕获除了与程序退出(sys.exit())相关之外的所有异常。

在继续向下看之前,你可以先思考一下上述例子可能出现的结果是什么,也可以自己尝试着在编译器里输入一下。思考完了请继续往下看。

实际上在 Python2 中的上述用例什么也不输出,而在 Python3 中则会出现下面的结果:

代码语言:javascript
复制
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    print(e)
NameError: name 'e' is not defined

竟然报错了,那么这到底是为什么呢?

其实这是因为在 Python3 中使用 as 分配异常的时候,在 except 的末尾将会把这个异常清除掉。这就好像将上面的示例变成下面的样子:

代码语言:javascript
复制
e = 429

try:
    raise Exception()
except Exception as e:
    try:
        pass
    finally:
        del e

print(e)

通过上面的变形代码,我们可以很清楚的看明白发生这一切的根源是什么:因为 e 被删除了。这也变相的告诉我们,如果想要在 except 后面引用 e,必须将它先赋值给其它变量。

这样看来,是变量 e 执行了 except 子句而被删除,但是为什么 e 会去执行 except 子句呢?仅仅是因为 e 和 as 后面的 e 长的一毛一样?

答案是否定的,其实这个是因为子句在 Python 中没有独立的作用域,所以上述示例中的所有内容都处于同一个作用域里,所以变量 e 会因为执行了 except 子句而被删除。

而在 Python2 中,Exception() 实例被赋值给了变量 e,因为正常的 Exception() 示例打印出来就是空,所有当我们尝试打印结果的时候,它的输出为空。我们可以用交互模式中的编译再来看一下:

代码语言:javascript
复制
>>> e = 429
>>> try:
...     raise Exception()
... except Exception as e:
...     pass
... 
>>> e
Exception()
>>> print(e)

>>>

以上,结果确实如此。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python空间 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档