名称空间(namespaces)
名称空间:存放名字的地方,是对栈区的划分
官方文档:
A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries。
命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。
名称空间分为三种:
内置名称空间
存放的名字:存放的是Python解释器内置的名称,比如print , input
存活周期:python解释器启动则产生,python解释器关闭则销毁
全局名称空间
存放的名字:只要不是函数内定义、也不是内置的、剩下的都是全局变量
存活周期:python文件执行则产生,python文件运行完毕后销毁
局部名称空间
存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
存活周期:在调用函数时存活,函数调用完毕后则销毁
名称空间的加载顺序
内置名称空间>全局名称空间>局部名称空间
名字查找优先级:当前位置向上一层一层查找
如果在局部名称空间: 局部——>全局——>内置名称空间
input = 333
def func():
input = 222
print(input)
func()
优先在局部名称空间内查找,也就是在函数内部寻找,所以最先输出的222。
将函数内部的input注释,会在全局名称空间内寻找,输出的是333
如果将全局名称也注释,就会在内置名称空间内找 输出
<built-in function input>
如果在全局名称空间:全局——>内置名称空间
input = 333
def func():
input = 222
func()
print(input)
'''
333
'''
名称空间的“嵌套”关系是以函数定义阶段为准,与调用位置无关
x = 1
def func():
print(x)
def foo():
x = 222
func()
foo()
'''
1
'''
作用域
作用范围
全局作用域:内置名称空间、全局名称空间
- 全局存活
- 全局有效
def foo():
x=111
print(x)
print(y)
def func():
y=222
print(x)
print(y)
x=333
y=444
foo()
func()
'''
111
444
333
222
'''
局部作用域:局部名称空间
- 临时存活
- 局部有效:函数内有效
LEGB规则
L —— Local(function);函数内的名字空间
E —— Enclosing function locals;外部嵌套函数的名字空间(例如closure)
G —— Global(module);函数定义所在模块(文件)的名字空间
B —— Builtin(Python);Python内置模块的名字空间
#builtin
#global
def f1():
#enclosing
def f2():
#enclosing
def f3():
#local
pass
gloal与nonlocal
在局部名称空间直接操作全局名称,而不是产生新的值。!全局的名字必须为不可变类型
x=111
def func():
#gloal x 声明这个x是全局的名字,不要再造新的名字
x=222
func()
print(x)
'''
111
去掉注释就是
222
'''
nonlocal (了解)
修改函数外层函数包含的名字对应的值(不可变类型)
x = 111
def f1():
x = 222
def f2():
nonlocal x
x = 333
f2()
print(x)
f1()
'''
333
'''
测试题
试题1:
以下输出的结果是?
x=111
def func():
print(x)
func()
输出的结果是111
试题2:
以下输出的结果是?
def func():
print(x)
x=111
func()
输出结果是报错?还是111
输出的结果是111
需要抛弃惯性思维,函数局部名称空间内找不到相应的值,是去上一层,也就是全局名称空间找,不能从代码的顺序上找,也就是不能从上而下去寻找。
试题3:函数的嵌套定义
以下输出的结果是?
input=111
def f1():
def f2():
print(input)
input=222
f2()
f1()
输出的结果是222,思路同试题2一致,在当前局部名称空间无法找到名字时,需要返回上一层,而不是从代码顺序的上方找。
试题4:
输出的结果是?
x=111
def func():
print(x)
x=2222
func()
结果是报错。
UnboundLocalError: local variable 'x' referenced before assignment
'''
局部变量x在定义之前就被引用了
'''
在函数定义阶段,函数扫描到了函数内部有x,语法是没有问题。但是在函数调用的时候,发现x未被定义。
名字的查找顺序是以函数定义阶段为准