我是python中的新手,请用示例描述Scopes和Namespaces之间的区别。
提前致谢
答案 0 :(得分:10)
你可以想到"范围"作为您可以从代码中的特定点访问的名称集。
x = 1
y = 2
def foo():
z = 3 + y
# Here, I have access to `x, y, foo` -- They are in the current scope
# `z` is not in the current scope. It is in the scope of `foo`.
a = x + y
b = x + z # NameError because `z` is not in my scope.
请注意,在函数foo
中,我可以访问"封闭"范围。我可以从函数内部定义的任何名称读取,也可以在创建函数的环境中定义任何名称。
在示例中,在foo
的函数内,范围包含x
,y
,foo
,z
和a
(如果要定义b
并且不抛出b
,它将包含NameError
。
______________________________
| |
| Names in enclosing scope |
| {x, y, foo, ...} |
| |
| -------------------- |
| | function scope | |
| | {z} | |
| | (Also has access | |
| | enclosing scope) | |
| -------------------- |
| |
------------------------------
命名空间是一个相关的概念。它通常被认为是一个拥有一组名称的对象。然后,您可以通过查看对象的成员来访问名称(以及它们引用的数据)。
foo.x = 1
foo.y = 2
foo.z = 3
此处,foo
是命名空间。我想你可以把命名空间看作一个名字的容器。 python中最自然的命名空间单位是module
,但是class
,类的实例,函数可以是命名空间,因为你可以将任意名称/数据附加到它们在大多数情况下。
请注意,在python中,这些概念变得有点混乱,因为您可以将模块的范围导入为命名空间
# foo.py
x = 1
y = 1
# bar.py
import foo
print foo.x
print foo.y
请注意"全球"在此示例中,foo
的范围作为命名空间bar
导入foo
的全局范围。
如果我们愿意,我们也可以将foo
的全局范围导入bar
的全局范围而不使用命名空间(尽管通常不鼓励这种做法):
# bar.py
from foo import *
print x
print y