Python中作用域和名称空间之间的关系是什么?


12

在许多资源中,我发现“作用域”“命名空间”可互换使用,这似乎有点令人困惑,因为它们的含义不同。

  • 范围定义了可使用名称的代码区域。
  • LEGB规则定义了查找名称的方式。
  • 命名空间是您查找名称的地方。

然后我读到:

  • “名称根据其分配的位置绑定到名称空间...”(我认为这是处理词法作用域中的作用域的方法)。
  • “功能添加一个额外的命名空间层,你的程序” [ 参考。](他们不添加额外的本地范围吗?)
  • “在函数定义内分配的所有名称都放在本地范围(与函数调用关联的名称空间)中。”
  • “全局作用域-即一个命名空间,在该命名空间中存在(分配)在模块文件顶层的变量。”

*所有报价均来自学习python第5版ch17

Python中的名称空间是实现范围的方式吗?它们是一样的吗?谁能启发我?


1
您能否提供引号的参考-我可以找到一个,但找不到另一个。
jonrsharpe 2015年

1
命名空间只是范围的一种类型。见stackoverflow.com/questions/291978/...
罗伯特·哈维

Answers:


16

命名空间是一个字典,映射名称(字符串),以值。当您进行赋值(例如)时a = 1,您就是在更改名称空间。当您进行引用(如)时print(a),Python会浏览一系列名称空间,以尝试找到名称作为关键字的名称空间。

一个范围定义哪些命名空间会以什么顺序来看待。任何引用的范围始终始于本地名称空间,然后向外移动直至到达模块的全局名称空间,然后再继续到builtins(该行引用了Python的预定义函数和常量的名称空间,例如rangegetattr)。 。

假设您有一个名为的函数inner,嵌套在一个名为的全局函数中outer,并且inner包含对名称的引用。Python首先在inner名称空间中查找。如果名称不存在,Python将在outer名称空间中查找。如果失败,Python将尝试模块的global名称空间,然后是builtin名称空间,NameError如果找不到该名称,最终将抛出一个。

当我们说x在函数的名称空间中时,是指它在函数内部本地定义。当我们说的x是函数的作用域时,x是指在函数的名称空间中或函数名称空间嵌套在其中的任何外部名称空间中。

无论何时定义函数,都将创建一个新的名称空间和一个新的作用域。命名空间是名称的新的本地哈希。范围是隐含的名称空间链,它从新的名称空间开始,然后遍历所有外部名称空间(外部范围),直到全局名称空间(全局范围)以及内建函数。

这些术语几乎可以互换使用,但这不是因为它们含义相同。这是因为它们在暗示的内容上有很多重叠。


3
“这些术语几乎可以互换使用,但这不是因为它们含义相同;而是因为它们在含义上有很多重叠。”
Nikos,2015年

2
这个答案在精神上是正确的,但在细节上是错误的。Python中的类未引入新的名称空间,这就是为什么类属性必须用类名限定以及为什么实例属性必须用实例名限定的原因。从内部到外部,Python中命名空间的级别是本地,封闭,全局和内置。可以在任何这些级别上定义类,但是类的成员必须始终是合格的。
罗布·史密斯

你是对的。上课不像我说的那样。我以为它们创建了像函数这样的词法作用域,但事实并非如此。如果您有时间,请更新答案,否则我会在某个时候做。谢谢。
卡尔·史密斯,

1
+1出色的答案,如此经济地囊括了这些微妙之处。我发现这非常有帮助,谢谢!
搜寻者

1
“命名空间是名称,值对,很像一个Python字典的哈希值” -我敢肯定的命名空间存储为Python字典。例如,您可以通过调用globals()来编辑全局名称空间,该名称空间使您可以直接修改字典以绑定对象和名称:例如globals()[name] =“ object”。否则,答案很好。
伊万·罗西卡

4

有Python的命名空间的优秀文章在这里。引用相关部分来回答您有关范围和名称空间之间的引用的问题:

范围是指程序的一个区域,可以从该区域访问没有前缀的名称空间。

例如,想象一个简单的压模程序:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll 有自己的名称空间,但模块名称空间中的名称也属于作用域


@CarlSmith指出,早期的Python文档说了同样的话:“作用域是可直接访问名称空间的Python程序的文本区域。此处的“直接访问”是指对名称的不合格引用尝试查找名称。在名称空间中。”
jonrsharpe

除了非本地/封闭范围之外,@ CarlSmith发生了很大变化吗?我想我们说的是同一件事-命名空间包含名称和值,作用域告诉您可以访问哪些命名空间。
jonrsharpe 2015年

我删除了旧评论。
卡尔·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.