名称空间(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
'''

作用域

作用范围
全局作用域:内置名称空间、全局名称空间

  1. 全局存活
  2. 全局有效
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
'''

局部作用域:局部名称空间

  1. 临时存活
  2. 局部有效:函数内有效

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未被定义。
名字的查找顺序是以函数定义阶段为准