名称空间与作用域
一:名称空间:就是存放名字的地方
1.内置名称空间:存放的是内置的名字,如print\input\len
生命周期:解释器启动则产生,解释器关闭则销毁(解释器自带的内置函数)
2.全局名称空间:存放的是顶级的名字
生命周期:python程序运行时则产生,python程序结束则销毁
x=10
def func():
x=11
print(x)
print(x)
func()
3.局部名称空间:函数内的名字
生命周期:调用函数时则产生,函数调用结束则销毁
名字查找的优先级
从当前位置往外查找,如果当前是在局部:局部名称空间——>全局名称空间——>内置名称空间
从当前位置往外查找,如果当前是在全局:全局名称空间——>内置名称空间
示范1:
def func():
len=22
print(len)
len=11
func()
print(len)
名称空间可以理解为一层套一层的关系,问题是嵌套关系是在函数定义阶段生成的,还是调用阶段生成的?
x=111
def foo():
print(x) #在定义阶段直接确定这个变量x
#最后打印出来的是定义阶段的全局x=111
或在调用阶段,foo在bar的内部调用,那么首先接收到的是bar里面的x=222
最后的结果是x=111,所以嵌套关系是在函数定义时确定的
def bar(f):
x=222 #在调用阶段,定义x=222,然后执行函数foo
f()
bar(foo)
#说明名称空间的确定是在定义阶段,检测语法的阶段
练习
len=0
def f1():
# len=1
def f2():
# len=2
print(len)
f2()
f1()
一层套一层,从局部到全局到内置的一个打印
全局范围/全局作用域:内置名称空间+全局名称空间
特点:全局存活,全局有效
局部范围/局部作用域:局部名称空间
特点:临时存活,局部有效
了解:
global(*)
nonlocal()
案例1:
x=10
def func(x):
#x = 值10的内存地址
x=20
#全局与局部同种变量名没有发生关联
print(x)
func(x)
print(x)
案例2:
x=[111,222,333]
def func(x):
#x = 值10的内存地址
x[0]=999
#有内存地址进来,且这是主动传入进来的
func(x) #产生了调用,传入x=[111,222,333]的内存地址
print(x)
案例3:
x = [11,22,33]
def func():
x[0] = 66666
#没有内存地址进来,发生了关联,相当于内层没有,去外层找这个内存地址
func()
print(x)
总结:当外部变量是不可变类型,函数内的局部不能发生更改(除了调用内置函数)。
当外部变量是可变类型时,函数局部可以根据索引或是关键字去外部找到内存地址,或是外部将内存地址导入进来,发生更改。