Python学习笔记:命名空间和作用域

学习Excel技术,关注微信公众号:

excelperfect

在Python中,任何“东西”都是一个对象。当我们赋值整数给变量时,例如x = 1,我们告诉Python在引用x时,意味着Python指向整数类型对象1,以便对数值计算或其他方法使用值1。

“命名空间”是Python用于查找给定变量名称并检索与其关联的对象的字典,正式称作“映射”变量名称到对象。

要获取Python可以访问的名称列表,可以使用dir函数。在前面的文章中,使用过此函数来确定对象的哪些属性是可访问的,但是通过执行不带参数的函数,可以返回当前命名空间中所有变量的列表。

图1

这些是可从终端或模块中的普通Python实例访问的高级对象。可以使用id函数来确定Python对象的id:

图2

作用域

了解更多关于这些命名空间的原因在于想知道在给定时间可以使用哪些变量。在Python命名空间的上下文中,“作用域”是与特定环境相关的名称集合。

图3

在Python中引用名称时,解释器在命名空间中从上图3的最小作用域开始搜索,并逐渐向外移动,直到Python找到名称或触发NameError异常。

内置作用域

内置作用域包含内置于通用Python的所有Python函数,包括常用功能例如print和dir。每当指定其中一个内置函数时,Python将搜索直到它在内置作用域的命名空间中找到函数的名称。内置作用域是Python使用的最宽广的作用域,意味着如果在较小作用域内再次定义内置作用域内的任何名称,则将使用较小作用域内的名称。如果使用内置名称作为新变量,这可能是不利的。

图4

变量定义的名称与内置名称冲突,有效地删除了使用print函数的功能。但是,还没有删除print函数,它只是在作用域内到达的第一个名称。print函数仍然存在,但要到达它,必须手动指定内置作用域才能找到它。这可以通过指定在启动Python解释器时自动导入指定的内置模块__builtin__来完成。

图5

模块作用域

内置命名空间作用域之下是模块作用域。模块作用域包括在Python的执行模块或终端中在任何类或函数之外定义的所有名称。这是我们在将对象赋值给变量时通常会考虑的命名空间:

图6

这意味着如果模块中定义的对象在外围作用域内不存在,则它们可以访问此命名空间:

图7

基于我们之前关于函数的讨论,这似乎违反常规。在上面的例子中,x没有在函数f中定义,因此我们认为解释器会触发NameError异常。但是,由于Python使用的作用域重叠模型,因此将在更高级别的作用域中(本例中为模块作用域)中搜索变量名称x并返回到该函数。

注意,虽然我们在上面的例子中已经看到可以引用更高级别作用域中的名称,但应该避免使用这种对象引用方法。因为变量可以在任何更高级别的作用域中找到,所以在较小作用域内可能存在关于引用哪个变量的模糊性。建议只有传递给函数输入的变量才能在函数中使用,并假设只有函数返回的变量才能在主程序中使用。

本地作用域和外围作用域

本地作用域是程序“当前”级别的命名空间,这是在函数、类或导入的模块而不是主模块中。例如:

图8

记住,本地命名空间不是所有嵌套函数、类或模块的最低级别,而是代码执行的级别。

图9

本地作用域和模块作用域之间的命名空间被视为外围作用域。在上面的代码中,method函数的x在其本地作用域内定义为3,在外围example作用域中定义为2,在模块作用域中定义为1。method作用域无法访问在func作用域内定义为4的x。

重新定义作用域的语句

下面介绍如何手动将变量赋值给不同的命名空间,能够将已定义变量的作用域移到其本地命名空间之外可能很重要。例如,在上节的最后一个代码块中,我们无法访问在最小作用域内赋值为5的x变量。在作用域之间传递变量的正确方法是通过输入元组将对象传递给函数,并通过函数return调用返回值。但是,在某些情况下执行此操作可能很棘手。为此,Python提供了global语句和nonlocal语句。

global语句

在任何命名空间中,使用global语句声明的变量将立即从模块作用域存储和检索该变量。

图10

在method命名空间中,将x声明为全局变量,或模块命名空间中的变量。在global语句之后,对x变量的更改也会更改模块作用域内的该变量,从而导致模块作用域x的最终打印为3。

注意,在上面的代码中,在一个命名空间中将x定义为全局的并不会永远声明该名称位于模块作用域内。可以看到,在func将该值赋值为4之后,它仅在func命名空间中保留。global语句仅用于声明调用在模块作用域内定义的命名空间内的变量。

nonlocal语句

在global语句用于在模块作用域内声明变量的情况下,nonlocal语句声明该变量在相邻外围命名空间的作用域内。例如:

图11

可以看到,nonlocal语句允许Python在method命名空间中声明变量x,也在相邻的外围命名空间example中。这并没有改变任何外部作用域内该变量的赋值,因而模块命名空间仍然将x赋值为1。

注意,如果相邻外围作用域是模块作用域,则nonlocal语句将失败:

图12

如果相邻的外围作用域是模块作用域,则需要使用global语句。

原文发布于微信公众号 - 完美Excel(excelperfect)

原文发表时间:2019-05-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券