🍖名称空间与作用域

引入

栈区 / 堆区

  • 栈区 : 存放的是变量名与变量值的内存地址映射关系
  • 堆区 : 存放的是值真正的位置

栈区和堆区

一.名称空间

1.什么是名称空间

  • 存放名字与值绑定关系的地方
  • 名称空间是一个虚拟的概念, 栈区才真实存在

2.为什么要有名称空间

  • 有了名称空间后就可以在内存的栈区存放相同的名字, 并且不会冲突

3.名称空间是否有包含关系?

  • 名称空间本质之间是没有包含关系的, 并且相互独立

名称空间的关系

二.名称空间的分类(三类)

1.内置名称空间

  • 存放内置的名字
  • 周期 : 在解释器启动时就产生,解释器关闭则失效
例如我们常用的内置函数
print
len
input

2.全局名称空间

  • 存放的是顶级的名字 (文件级别的名字)
  • 周期 : 在执行文件时生效,文件运行完毕或文件执行期间被删除则失效
x = 1      #全局名称空间
def foo(): #全局名称空间
	y = 2

注意,"if"下面的定义的变量名都是全局的
if 1 > 0        
	z = 3        #全局
	if 3 > 0: 
		p = 555  #全局

3.局部名称空间

  • 存放函数内定义的名字
  • 周期 : 在函数调用时临时生效, 函数结束时则失效
def f()
	x = 222    #局部名称空间
    
f()   #函数调用结束失效

4.名称空间的加载顺序

'内置名称空间'----->'全局名称空间'----->'局部名称空间'

5.名称空间的查找优先级

'局部名称空间'----->'全局名称空间'----->'内置名称空间'

6.名称空间的销毁顺序

'局部名称空间'----->'全局名称空间'----->'内置名称空间'

7.名称空间总结与注意事项

  • 重要概念:名称空间的嵌套关系是在函数定义阶段(检测语法)时确定的,与函数调用的位置无关,与函数定义位置有关

  • 三种名称空间必须要有的是 : 内置名称空间, 全局名称空间

  • 查找优先级示例

从"f2"局部开始找
x = 3
def f1():
    x = 2
    def f2():
        x =1
        print(x)
    f2()
f1()  # 1

将"f2"局部的删除,就往上一层找,找到"f1"
x = 3
def f1():
    x = 2
    def f2():
        print(x)
    f2()
f1()  # 2

再将"f1"里面的删除,于是找到了全局
x = 3
def f1():
    def f2():
        print(x)
    f2()
f1()  # 3
  • 函数的嵌套定义示例
在定义"f2"的之后,有定义了同一级别的"len",所以当打开函数"f2"运行的时候,本着优先级查找就先找到了"222"
len = 111
def f1():
    def f2():
        print(len) # 222
	len = 222
    f2()
f1()  # 222

三.作用域

1.什么是作用域

  • 作用域就是根据名称空间的范围和特点进行了归类
  • 查看作用域 : globals( ), locals( )

2.全局作用域

  • 包含 : 内置名称空间, 全局名称空间
  • 特点 : 全局存活, 全局有效

3.局部作用域

  • 包含 : 局部名称空间
  • 特点 : 临时存活, 局部有效

4.L E G B

  • LEGB 代表名字查找顺序 : L--->E--->G--->B
  • locals : 是函数内的名字空间, 包括局部变量和形参
  • enclosing : 外部嵌套的名称空间(闭包中常见面)
  • globals : 全局变量, 函数定义所在模块的名字空间
  • builtins : 内置模块的名字空间

四.global 与 nonlocal关键字

1.global 关键字

  • 使用方法 : global x 声明这个 x 是全局变量
  • 针对的是不可变类型的值
在全局空间定义一个变量"x",函数"foo",在函数内部修改"x"的值
x = 111
def foo():
    x = 222
    
foo()
print(x)   #111
#发现并无软用

使用"global"关键字之后
x = 111
def foo():
    global x  # 声明下面的"x"属于全局
    x = 222
    
foo()
print(x)  #222
#发现成功了

2.nonlocal 关键字

  • 使用方法 : nonlocal x ,声明外层函数的局部变量
  • 修改该函数外层函数包含的变量名对应的值, 也是针对不可变类型
  • 注意 : 只能在局部名称空间中查找, 先从外部嵌套的函数找, 没找到再往上找, 如果都没找到则报错
不做任何处理,此函数应该是打印"f2"函数下的"x = 333"
x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            x = 444
        f3()
        print(x)  #333
    f2()
f1()  # 333

使用"nonlocal"关键字
x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            nonlocal x  #将下面的"x = 444"变成了上一层的"x"的值
            x = 444
        f3()
        print(x) 
    f2()
f1()  # 444

如果外层函数都没有"x"这个值,报错
x = 111  #并不会去全局修改
def f1():
    def f2():
        def f3():
            nonlocal x
            x = 444
        f3()
        print(x)
    f2()
f1()  #报错
原文地址:https://www.cnblogs.com/songhaixing/p/14051159.html