一、命名空间的定义

  变量名和变量值的映射

  命名空间是用字典实现, key就是变量的名,value就是变量值

二、命名空间的分类

  python程序执行的过程中, 同时会有2-3个活动的命名空间(函数调用时,有3个命名空间, 函数调用结束后,有两个命名空间) 

  根据变量的位置, 将命名空间分为三类:

    局部命名空间:Local, 指的是函数所拥有的命名空间, 包括函数的入参,函数内部的局部变量
    全局命名空间:Global, 指的是模块(.py文件)所拥有的命名空间, 包括函数, 类, 全局的变量,导入模块中的内容
    内建命名空间:Build-in, 指的是python内置的函数和异常.

    同一个命名空间中,变量名不能重复; 不同的命名空间之间,变量名互不影响

三、命名空间的生命周期

  局部命名空间:函数调用的时候创建, 函数调用结束后被删除
  全局命名空间:模块被加载的时候创建, python解释器退出的时候被删除
  内建命名空间:随着python解释器的启动而创建, python解释器退出的时候被删除

四、命名空间的访问

  locals() 用这个函数可以访问到局部的命名空间
  globals() 用这个函数可以访问到全局的命名空间

  标准的情况是:
    在局部中, 使用locals()
    在全局中, 使用globals()

  特殊情况:
    在局部中, 使用globals(), 查看到的不是全局命名空间中所有的内容
    而是, 在局部中能访问到的全局命名空间中的内容

五、命名空间的创建顺序

  python解释器启动 --> 创建内建命名空间 --> 加载模块 --> 创建全局命名空间 --> 函数的调用 --> 创建局部命名空间

六、命名空间的销毁顺序

  函数的调用结束 --> 销毁局部命名空间 --> python解释器退出 --> 销毁全局命名空间 --> 内建命名空间 

  总结一下: 局部命名空间是随着函数的调用动态的创建出来的, 随着函数调用的结束动态销毁的

七、作用域

  1、概念:针对变量而言, 程序执行的过程中,变量能够起作用(可应用)的范围
        * 只有 函数, 类, 模块 会产生作用域, 代码块不会产生作用域

  2、作用域的分类:
    根据变量的位置,可以将作用域分为四类(LEGB)
    Local:局部作用域(函数内部的作用域)
    Enclosing:封闭作用域(两层函数嵌套, 外层嵌套函数的作用域)
    Global:全局的作用域(模块的作用域)
    Bulid-in:内建的作用域(python内置的)

  3、作用域的查找规则, 遵循LEGB法则

    按顺序依次在局部作用域,封闭作用域,全局作用域,内建作用于中进行查找,一旦查找到了,就不会继续进行查找
    如果在LEGB中都没有查找到, 则会发生异常: NameError: name 'abc' is not defined

    (1)局部作用域中可以访问到 局部作用域, 封闭作用域, 全局作用域, 内建作用域中的变量
    (2)封闭作用域中可以访问到 封闭作用域, 全局作用作用域域, 内建作用域中的变量
        封闭作用域不能访问到局部作用域中的变量
    (3)全局作用域中可以访问到 自己和内建作用域中的变量
        不能访问到封闭作用域和局部作用域中的内容 

八、区别

  局部变量: 在函数内部声明的变量, 只在函数中有效
  全局变量: 在模块中声明的变量, 在整个模块中有效

  全局变量是不可变数据类型, 函数无法修改全局变量的值
  全局变量是可变数据类型时, 函数可以修改全局变量的值
  (如果给函数传递的参数是 全局可变类型数据, 在函数多次调用的过程中, 全局变量会发生改变)

九、关键字

  global : 在局部作用域中标记一个变量为全局变量
       可以将局部变量变成一个全局变量

  nonlocal : 在局部作用域中标记一个变量是外层封闭作用域中的变量
      可以修改外层(非全局)变量