Python 名称空间与作用域
2018-01-20 08:51
603 查看
这篇文章介绍 Python 的名称空间以及变量的作用域。
例如,在
输出:
43547988
43547988
可以看到,两都均指向同一个对象。我们再来看复杂一点的代码。
输出:
id(a) = 55606612
id(a) = 55606600
id(3) = 55606600
id(2) = 55606612
id(b) = 55606612
上述的代码发生了什么呢?我们以图1来说明。
图1:Python 的名称与对象
起初,名称
然后,执行操作
最后,执行
这个例子也展示了 Python 在执行变量的赋值时,并不会重复创建一个对象的事实。名称采用动态绑定的机制使得 Python 更加高效,同一个名称可以引用不同类型的对象。
可以看到,
名称空间是名称到对象的映射。
在 Python 中,名称空间采用字典来实现。Python 的名称空间包括:
内置名称空间,例如,内置名称空间包含 Python 的内置函数,如,
模块名称空间,全局名称空间,在模块内定义的名称
局部名称空间,例如,在函数(function)或者类(class)被调用时,其内部包含的名称
不同的名称空间内的名称不会相互冲突,即是它们采用相同的名称。这也正是名称空间的作用。
内置名称空间在 Python 解释器启动时就创建了,直到 Python 解释器退出时内置名称空间才失效。这使得我们可以在程序的任何位置使用内置名称空间内的名称,例如,
模块名称空间当模块被引用时创建,直到 Python 解释器退出时模块名称空间才失效。
函数名称空间在函数被调用时创建,函数返回后失效。
图2:Python 的名称空间
函数作用域,包括了函数内的局部名称
模块作用域,包括了模块内的全局名称
内置作用域,包括了内置名称
当在函数内部使用一个名称时,为了查找出该名称所引用的对象,Python 解释器先在函数名称空间查找,接着在模块名称空间查找,最后在内置名称空间查找,直到寻找到该名称为止。
当函数 A 处于函数 B 的内部时,函数 A 的作用域处于函数 B 作用域之内。
在这个例子中,名称
当我们在函数
我们使用以下的例子来说明。
输出:
a = 30
a = 20
a = 10
在函数
为了在函数作用域中对全局的名称进行读取或者赋值操作,需要将这个名称声明为
输出:
a = 30
a = 30
a = 30
可以看到,通过
https://docs.python.org/3/tutorial/classes.html
https://www.python-course.eu/namespaces.php
https://www.python-course.eu/global_vs_local_variables.php
https://www.programiz.com/python-programming/modules
https://code.tutsplus.com/tutorials/what-are-python-namespaces-and-why-are-they-needed–cms-28598
https://bytebaker.com/2008/07/30/python-namespaces/
https://stackoverflow.com/questions/3190706/nonlocal-keyword-in-python-2-x
Python 的名称
Python 的名称(Name)是对象的一个标识(Identifier)。我们知道,在 Python 里面一切皆对象,名称就是用来引用对象的。说得有点玄乎,我们以例子说明。例如,在
a = 2这个语句中,
2是个存储在内存中的一个对象,名称
a则会引用
2这个对象,“引用”的含义是指可以通过名称
a来使用
2这个对象。我们可以使用
id()函数来获取对象的地址。
a = 2 print(id(2)) print(id(a))
输出:
43547988
43547988
可以看到,两都均指向同一个对象。我们再来看复杂一点的代码。
a = 2 print 'id(a) = %s' % id(a) a = a + 1 print 'id(a) = %s' % id(a) print 'id(3) = %s' % id(3) b = 2 print 'id(2) = %s' % id(2) print 'id(b) = %s' % id(b)
输出:
id(a) = 55606612
id(a) = 55606600
id(3) = 55606600
id(2) = 55606612
id(b) = 55606612
上述的代码发生了什么呢?我们以图1来说明。
图1:Python 的名称与对象
起初,名称
a引用对象
2;
然后,执行操作
a = a + 1,这时对象
3被创建,名称
a引用对象
3,所以
id(a)和
id(3)输出相同的地址;
最后,执行
b = 2,名称
b引用对象
2,所以
id(2)和
id(b)输出相同的地址
这个例子也展示了 Python 在执行变量的赋值时,并不会重复创建一个对象的事实。名称采用动态绑定的机制使得 Python 更加高效,同一个名称可以引用不同类型的对象。
a = 5 a = 'hello world' a = [1, 2, 3]
可以看到,
a先后引用了数字,字符串,列表的类型的对象,这在 Python 中完全是合法的。
Python 的名称空间
了解 Python 的名称后,我们来看 Python 的名称空间。名称空间是名称到对象的映射。
在 Python 中,名称空间采用字典来实现。Python 的名称空间包括:
内置名称空间,例如,内置名称空间包含 Python 的内置函数,如,
abs()
模块名称空间,全局名称空间,在模块内定义的名称
局部名称空间,例如,在函数(function)或者类(class)被调用时,其内部包含的名称
不同的名称空间内的名称不会相互冲突,即是它们采用相同的名称。这也正是名称空间的作用。
内置名称空间在 Python 解释器启动时就创建了,直到 Python 解释器退出时内置名称空间才失效。这使得我们可以在程序的任何位置使用内置名称空间内的名称,例如,
id(),
print()等函数。
模块名称空间当模块被引用时创建,直到 Python 解释器退出时模块名称空间才失效。
函数名称空间在函数被调用时创建,函数返回后失效。
图2:Python 的名称空间
Python 变量的作用域
Python 的作用域(scope)决定了我们在程序中能否直接使用名称空间中的名称,直接访问的意思是指不需要在名称前添加名称空间的前缀。对于 Python 来说,至少存在以下三类的作用域。函数作用域,包括了函数内的局部名称
模块作用域,包括了模块内的全局名称
内置作用域,包括了内置名称
当在函数内部使用一个名称时,为了查找出该名称所引用的对象,Python 解释器先在函数名称空间查找,接着在模块名称空间查找,最后在内置名称空间查找,直到寻找到该名称为止。
当函数 A 处于函数 B 的内部时,函数 A 的作用域处于函数 B 作用域之内。
例子
def outer_function(): b = 20 def inner_func(): c = 30 a = 10
在这个例子中,名称
a在全局名称空间中,名称
b在函数
outer_function的局部名称空间,名称
c则在函数
inner_func的局部名称空间。
当我们在函数
inner_func时,
c是个局部的名称,
b是个非局部的名称,而
a则是个全局的名称。在函数
inner_func中,我们可以对
c进行读取操作和赋值操作,而只能对
b和
a进行读取操作。当对
b进行赋值时,一个新的名称将会被创建,这个新的名称处于
inner_func函数局部名称空间中。对
a进行赋值时也会在局部名称空间中创建一个新的名称。
我们使用以下的例子来说明。
def outer_function(): a = 20 def inner_function(): a = 30 print('a = %s' % a) inner_function() print('a = %s' % a) a = 10 outer_function() print('a = %s' % a)
输出:
a = 30
a = 20
a = 10
在函数
inner_function中,我们对
a进行了赋值操作,但函数
outer_function中的
a仍然为
20,全局名称空间中的
a则仍然为
10。
为了在函数作用域中对全局的名称进行读取或者赋值操作,需要将这个名称声明为
global。
def outer_function(): global a a = 20 def inner_function(): global a a = 30 print('a = %s' % a) inner_function() print('a = %s' % a) a = 10 outer_function() print('a = %s' % a)
输出:
a = 30
a = 30
a = 30
可以看到,通过
global,我们在不同的作用域对全局名称
a进行了赋值操作,最后在函数
inner_function中对
a的赋值也就是全局名称
a的值。
参考资料
https://www.programiz.com/python-programming/namespacehttps://docs.python.org/3/tutorial/classes.html
https://www.python-course.eu/namespaces.php
https://www.python-course.eu/global_vs_local_variables.php
https://www.programiz.com/python-programming/modules
https://code.tutsplus.com/tutorials/what-are-python-namespaces-and-why-are-they-needed–cms-28598
https://bytebaker.com/2008/07/30/python-namespaces/
https://stackoverflow.com/questions/3190706/nonlocal-keyword-in-python-2-x
相关文章推荐
- Python 名称空间与作用域
- python全栈开发-Day9 函数对象、函数嵌套、名称空间与作用域(装饰器基础)
- python 名称空间的作用域范围
- python函数篇:名称空间、作用域和函数的嵌套
- python基础:名称空间与作用域
- Python 的名称空间和作用域
- C++内存模型与名称空间(存储持续性、作用域、链接性、动态内存分配、命名空间)
- Python中的命名空间、作用域以及locals() 和 globals()
- Python基础-作用域和命名空间(Scope and Namespace)
- python记录_day10 动态传参 命名空间 作用域
- [妖路-1] 名称空间,作用域,生存期
- 名称空间 作用域 闭包
- Python命名空间和作用域窥探
- Python 之作用域和名字空间
- 函数的名称空间与作用域
- Python 作用域和命名空间
- Python(名称空间、函数嵌套、函数对象)
- Python的命名空间和作用域
- Python名称空间
- python的命名空间和作用域