系列文章目录

一、命名空间(namespace)

假设有一所学校,里面有十个名叫张三的同学。这时,王校长要李老师去把张三找来。

如果没有分班,所有的张三都在同一个大教室里上课,那么李老师就不知道该找哪个张三了。

但如果有了分了班,每个班只有一个张三,且不会有重名的同学,那么李老师就会询问校长要找的张三的班级,从而很快的把张三找来。

  • 含义:上述例子中的”班级“就相当于命名空间,可以把相同名称的变量分隔开来,避免名称方面的冲突。

python解释器把内存的栈区分为三块,对应三种命名空间:

1. 内置命名空间

  • 存放的名称:存放python解释器内置的各种名称,如print。
  • 存活周期:开始—python解释器启动;结束—python解释器关闭。

2.全局命名空间

  • 存放的名称:除了函数内部和类内部定义的名称,以及内置的名称外,都属于全局名称空间。
  • 存活周期:开始—程序开始运行;结束—程序运行结束。

3.局部命名空间

  • 存放的名称:函数内部以及类内部的名称,如函数内部定义的普通变量的名称。
  • 存活周期:开始—函数被调用时;结束—函数执行完毕。

4. 命名空间的加载、查找顺序

  • 加载顺序:

    内置—>全局—>局部

  • 查找顺序:

    局部—>全局—>内置

    注意:只会从左往右查找,如果当前在全局,只会向右查找全局和内置,不会查找局部。

二、作用域

  • 含义:作用域就是指一个变量的作用范围。

1. 四种作用域:

  • 局部作用域(local)
    函数中定义的变量的作用域叫做局部作用域。

  • 闭包作用域(enclosing)
    嵌套函数中,外层函数的局部作用域叫做闭包作用域。

    def foo():
        a = 1  # 名称a就属于闭包作用域
        def bar():
            pass
    
  • 全局作用域(global)

    范围:模块级别定义的变量的作用域叫做闭包作用域,比如在一个py文件内的,定义在所有函数和类外面的变量,它们的作用域就是全局作用域。

  • 内建作用域(build-in)

    范围:python解释器内部变量的作用域,如print的作用域就是内建作用域。

2. 变量查找顺序

LEGB规则:Local 局部 —> Enclosing 闭包 —> Global 全局 —> Built–in python内建

3. 修改作用域

修改作用域,在底层其实就是修改了命名空间

  • global关键字

    该关键字会使变量的作用域变成全局作用域。

  • nonlocal关键字

    该关键字会使变量的作用域向上升一级。比如:使嵌套函数内层变量的作用域,变成闭包作用域。

    def foo():
        a = 1  # 名称a就属于闭包作用域
        def bar():
            nonlocal a  # 此处a的作用域就与外层函数中的a相同了,两者处于同一个命名空间
            pass
    

    下一篇