目录
第二十七篇 名称空间与作用域
函数内部的函数只能在函数内部调用,不能再函数外部调用,要想知道为什么,我们就需要了解名称空间和作用域
一、名称空间
名称空间(name spaces):在内存管理那一章节中,我们知道变量的创建其实就是在内存开辟了一个新的空间。但是变量名的存储之前一直没有提及,其实在内存中有一块内存存储着变量名与变量之间绑定关系的空间,这个空间叫做名称空间
1.内置名称空间
- 1.内置名称空间:存放python解释器自带的名字,比如
int、float、len、strip
- 2.生命周期:在python解释器启动时生效,在python解释器关闭时失效
2.全局名称空间
- 1.定义:除了内置和局部的名字之外,其余都放在全局名称空间。如下面的
a、f、l、i
- 2.生命周期:在文件执行时生效,在文件执行结束后失效
a = 0
def f():
pass
l = [2,'k']
if 2>1:
if 0<1:
i = 6
3.局部名称空间
- 1.定义:用于存放函数调用期间函数体产生的名字。比如下面的
f2
- 2.生命周期:在文件执行时函数调用期间时生效,在函数执行结束后失效
def f():
def f2():
print('ha')
f2
f()
4.加载顺序
- 由于.py文件是由python解释器打开的,因此一定是在python解释器中的内置名称空间加载结束后,文件才开始打开,这个时候才会产生全局名称空间,但文件内有某一个函数被调用的时候,才会开始产生局部名称空间,因此名称空间的加载顺序为:内置名称空间---->全局名称空间---->局部名称空间
5.查找顺序
由于名称空间是用来存放变量名与值之间的绑定关系的,所以但凡要查找名字,就必须从名称空间中的三者之一找,查找顺序是,从当前的所在位置开始查找,如果当前所在的位置为局部名称空间,则查找顺序为:局部名称空间---->全局名称空局---->内置名称空间(也就是从当前位置开始,只会往外找)
x = 0 y = 1 def f(): x = 66 y = 233 print(x,y) f() # 66 233
```python
x = 0
def f():
print(x)
x = 6
f() #6
```
二、作用域
- 作用域就是作用的区域
- ==只需要记住:全局变量和局部变量,可能名字一样,但是两者根本不是同一种==
1.全局作用域
- 全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间
x = 6
def f():
print(x)
f() # 6
2.局部作用域
- 局部作用域:局部有效,临时存储,只包含局部名称空间
def f1():
def f2():
def f3():
print(x)
x = 1
f3()
f2()
f1() # 1
3.注意点
- 作用域关系在函数定义阶段就固定死了,与函数的调用无关
x = 1
def f(): # 函数定义阶段
print(x) # 由于f()函数的局部作用域没有x,所以会先去全局找,此时x=1
def f2():
x = 6 # 这个x只能在f2()函数的局部作用域起作用,对f()函数没有丝毫影响
f()
f2() # 1
4.函数对象与作用域应用
def f():
def f1():
print('hah')
return f1
a = f()
def f2():
a()
f2() # hah
三、补充知识点(不推荐使用)
1.global关键字
- 作用:修改全局作用域中的变量
x = 1
def f():
x = 6
def f2():
x = 233
f2()
f()
print(x) # 在当前位置查找,所以是全局作用域的x=1
x = 1
def f():
x = 6
def f2():
global x # 可以将局部变量变为全局变量
x = 233
f2()
f()
print(x) # 233
2.nonlocal关键字
- 修改局部作用域中的变量
x = 1
def f():
x = 6
def f2():
x = 233
f2()
print(x)
f() # 6
x = 1
def f():
x = 6
def f2():
nonlocal x # 可以使内部函数变量在外部也能使用,但不能修改为全局变量
x = 233
f2()
print(x)
f() # 233
3.注意点
1.在局部想要修改全局的可变类型,不需要任何声明,可以直接修改
2.在局部想要修改全局的不可变类型,需要借助global声明,声明为全局变量
lis = []
def f():
lis.append(1)
# 函数调用前
print(lis) # []
# 函数调用后
f()
print(lis) # [1]