Fork me on GitHub

名称空间与作用域

一:名称空间:就是存放名字的地方

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)

总结:当外部变量是不可变类型,函数内的局部不能发生更改(除了调用内置函数)。
当外部变量是可变类型时,函数局部可以根据索引或是关键字去外部找到内存地址,或是外部将内存地址导入进来,发生更改。

posted @ 2020-09-01 10:50  artherwan  阅读(122)  评论(0编辑  收藏  举报