名称空间介绍:
当Python解释器启动时,会自动开辟一块内存空间。每当遇到一个变量名的时候,就会把变量名和值的关系记录下来存到这块内存空间中。
我们给这个存放名称与值的关系的空间起了个名字,叫做——名称空间。
当函数定义时,解释器只把函数名读入内存,不关心函数内的具体代码。
当函数调用时,解释器就会另开一个内存空间,存放这个函数里面的变量。当函数调用结束时,就会清空这个函数内所有内容。
代码在执行时创建的存放变量与变量值关系的内存空间,叫做全局名称空间。
函数调用时,额外开辟的内存空间,叫做局部名称空间。
还有一种名称空间,叫做内置名称空间,这个空间存放的是Python定义好的名称,比如:len, max, min, sorted, bin, oct, hex等之类大家熟悉的名称。
名称空间里面包含哪些:
内置名称空间:Python解释器提前定义好的名称,已经存入内置名称空间。
全局名称空间:if,for,while,无论创建多少层,在里面创建的变量,都存放在全局名称空间中。
局部名称空间:函数内创建的变量都属于局部名称空间。
名称空间的生命周期:
全局名称空间:代码文件执行时创建,代码执行结束销毁。
局部名称空间:函数调用时创建,函数执行结束时自动销毁。
内置名称空间:Python解释器启动时创建,Python解释器关闭时销毁。
名称空间的查找顺序:
名称查找的第一步,找到自己的位置(大前提)。
如果自己在全局中,则查找顺序为:全局名称空间 >>> 内置名称空间
如果自己在局部中,则查找顺序为:局部名称空间 >>> 全局名称空间 >>> 内置名称空间
注意:函数在定义阶段,名称的查找顺序已经固定,不会因为函数的调用位置变化而变化。
def index(): x = 111 print(x) def index2(): print(x) x = 10 index() index2() >>> 111 >>> 10 说明:
index调用时,print(x)时,先查找index函数内的局部名称空间,局部名称空间中有x这个名称,取x的值打印。 index2调用时,创建index2局部名称空间,查找index2函数内的局部名称空间有没有x这个名称,发现没有,就查找比局部名称空间大的名称空间,在全局名称空间中发现有x,即取x=10的值打印。
练习一:
x = 111 def f1(): x = 222 def f2(): x = 333 def f3(): # x = 444 def f4(): # x = 555 print(x) x = 777 f4() # x = 777 f3() f2() f1() >>> 777
练习二:
def func(): x = 1 def index(): print(x) return index res = func() x = 999 res() >>> 1 说明:func函数的返回时index, res = func(),则res为func函数的返回值,res就是func的内部函数index,注意func返回值没有()。
函数名()表示调用,返回函数名表示返回这个函数对象。当res()时,表示调用index函数。
print(x),在index的局部名称空间中,没有x,就往上层找,在func的局部名称空间中,找到了名称x,即把 1打印。找到时不会再向上找。x=999为全部名称空间。即:函数定义时已经确定了名称查找顺序。
函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)
练习三:
x=111 def outer(): def inner(): print('from inner',x) return inner f=outer() x = 222 f() >>>'from inner' 222
练习四:
x=111 def outer(): def inner(): print('from inner',x) return inner f=outer() def func(): x=333 f() func() >>> 'from inner' 111
Python中的作用域分为两种:
全局作用域:全局有效:内置名称空间、全局名称空间
局部作用域:局部有效:局部名称空间
局部中修改全局变量:
在局部中,如果全局变量是可变类型,在局部中可以直接修改。如列表,可以通过append修改。但是不能直接复制修改。
x = [] def func(): x.append(1) func() print(x) >>> [1]
如果全局变量是不可变类型,局部中是不能修改的。
x = [] def func(): x = [1,2] func() print(x) >>> []
除非使用global关键字,可以在局部中直接修改全局变量的值。
x = 1 def func(): global x x = [1,2] func() print(x) >>> [1, 2]
在局部中修改局部变量:
通过nonlocal可以在局部中修改局部变量的值。
# nonlocal 局部修改局部 def func(): x = 1 def index(): nonlocal x x = 2 index() print(x) func() >>> 2 说明:如果不声明nonlocal x, 就不能修改局部变量x的值,打印出来的x为1.
global: 局部修改全局,想改多个时,可在变量间用 ,隔开:global x, y, z
nonlocal: 局部修改全局,想改多个时,可在变量间用 ,隔开:nonlocal x, y, z