名称空间介绍:

当Python解释器启动时,会自动开辟一块内存空间。每当遇到一个变量名的时候,就会把变量名和值的关系记录下来存到这块内存空间中。

我们给这个存放名称与值的关系的空间起了个名字,叫做——名称空间。

当函数定义时,解释器只把函数名读入内存,不关心函数内的具体代码。

当函数调用时,解释器就会另开一个内存空间,存放这个函数里面的变量。当函数调用结束时,就会清空这个函数内所有内容。

代码在执行时创建的存放变量与变量值关系的内存空间,叫做全局名称空间。

函数调用时,额外开辟的内存空间,叫做局部名称空间。

还有一种名称空间,叫做内置名称空间,这个空间存放的是Python定义好的名称,比如:len, max, min, sorted, bin, oct, hex等之类大家熟悉的名称。

名称空间里面包含哪些:

内置名称空间:Python解释器提前定义好的名称,已经存入内置名称空间。

全局名称空间:if,for,while,无论创建多少层,在里面创建的变量,都存放在全局名称空间中。

局部名称空间:函数内创建的变量都属于局部名称空间。

名称空间的生命周期:

全局名称空间:代码文件执行时创建,代码执行结束销毁。

局部名称空间:函数调用时创建,函数执行结束时自动销毁。

内置名称空间:Python解释器启动时创建,Python解释器关闭时销毁。

名称空间的查找顺序:

名称查找的第一步,找到自己的位置(大前提)。

如果自己在全局中,则查找顺序为:全局名称空间 >>> 内置名称空间

如果自己在局部中,则查找顺序为:局部名称空间 >>> 全局名称空间 >>> 内置名称空间

注意:函数在定义阶段,名称的查找顺序已经固定,不会因为函数的调用位置变化而变化。

defindex():
x= 111
print(x)defindex2():print(x)
x= 10index()
index2()>>> 111

>>> 10说明:

index调用时,print(x)时,先查找index函数内的局部名称空间,局部名称空间中有x这个名称,取x的值打印。

index2调用时,创建index2局部名称空间,查找index2函数内的局部名称空间有没有x这个名称,发现没有,就查找比局部名称空间大的名称空间,在全局名称空间中发现有x,即取x=10的值打印。

练习一:

x = 111
deff1():
x= 222
deff2():
x= 333
deff3():#x = 444
deff4():#x = 555
print(x)
x= 777f4()#x = 777
f3()
f2()
f1()>>> 777

练习二:

deffunc():
x= 1
defindex():print(x)returnindex
res=func()
x= 999res()>>> 1

说明:func函数的返回时index, res= func(),则res为func函数的返回值,res就是func的内部函数index,注意func返回值没有()。

函数名()表示调用,返回函数名表示返回这个函数对象。当res()时,表示调用index函数。

print(x),在index的局部名称空间中,没有x,就往上层找,在func的局部名称空间中,找到了名称x,即把 1打印。找到时不会再向上找。x=999为全部名称空间。即:函数定义时已经确定了名称查找顺序。

函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)

练习三:

x=111
defouter():definner():print('from inner',x)returninner
f=outer()
x= 222f()>>>'from inner' 222

练习四:

x=111
defouter():definner():print('from inner',x)returninner
f=outer()deffunc():
x=333f()
func()>>> 'from inner' 111

Python中的作用域分为两种:

全局作用域:全局有效:内置名称空间、全局名称空间

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

局部中修改全局变量:

在局部中,如果全局变量是可变类型,在局部中可以直接修改。如列表,可以通过append修改。但是不能直接复制修改。

x =[]deffunc():
x.append(1)
func()print(x)>>> [1]

如果全局变量是不可变类型,局部中是不能修改的。

x =[]deffunc():
x= [1,2]
func()print(x)>>> []

除非使用global关键字,可以在局部中直接修改全局变量的值。

x = 1
deffunc():globalx
x= [1,2]
func()print(x)>>> [1, 2]

在局部中修改局部变量:

通过nonlocal可以在局部中修改局部变量的值。

#nonlocal 局部修改局部

deffunc():
x= 1
defindex():
nonlocal x
x= 2index()print(x)
func()>>> 2

说明:如果不声明nonlocal x, 就不能修改局部变量x的值,打印出来的x为1.

global: 局部修改全局,想改多个时,可在变量间用 ,隔开:global x, y, z

nonlocal: 局部修改全局,想改多个时,可在变量间用 ,隔开:nonlocal x, y, z