名称空间与闭包

发布时间 2023-12-13 21:42:30作者: 桃源氏

名称空间与作用域

一、名称空间与闭包

[1]什么是名称空间?

  • 名称空间即存放名字与对象映射/绑定关系的地方
  • 在程序执行期间最多会存在三种名称空间
x = 3 # 给变量赋值的时候就给3这个变量值开辟了一个命名为x的名称空间
del x # 这里删除了这个变量名与对象的的映射,所以下面输出是就会报错
print(x) # NameError: name 'x' is not defined

[2]内建名称空间

  • 内建名称空间就是伴随着解释器启动和关闭一起产生和关闭的内存空间
    • 如一些与预加载的的函数max,min等

[3]全局名称空间

  • 伴随python文件的开始执行/完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中(我们的定义的变量等)

[4]局部名称空间

  • 伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中

[5]名称空间的加载顺序

  • 内置名称空间->全局名称空间->局部名称空间,

  • 而查找一个名字,必须从三个名称空间之一找到,查找顺序为:

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

二、作用域

[1]变量的作用域

  • Python是静态作用域,也就是说Python中,变量的作用域源于它在代码中的位置

  • 在不同的位置,可能有不同的命名空间。命名空间是变量作用域的体现形式

  • python变量作用域一般有4种:

    • Local(局部变量)
    • Enclosed(嵌套)
    • Global(全局)
    • Built-in(内置)

(1)Local(局部变量)

  • Local(局部变量):暂时的存在,依赖于创建该局部作用域的函数。当函数没有被调用时,函数内的局部变量就不存在。

  • 作用范围:当前整个函数体范围

    def add():
        x = 1
        print(x)  # 1 
    
    
    print(x)  # NameError: name 'x' is not defined x 只作用于add函数内外面无法引用
    

(2)Enclosed(嵌套)

  • Enclosed(嵌套):一般是在函数中嵌套函数的时候,外层函数的变量作用域。
  • 作用范围:闭包函数
def methon1():
    x = 1
    print(f'这是外层函数打印的:{x}')  # 这是外层函数打印的:1

    def methon2():
        
		#外层函数中定义的变量内层可以用
        # 函数 func1 里面 嵌套的 函数 func2 里面的作用域就是 嵌套作用域
        print(f'这是内层函数打印的:{x}')  # 这是内层函数打印的:1
		
    methon2()


methon1()

(3)Global(全局)

  • Global(全局):一般模块文件顶层声明的变量具有全局作用域,从外部来看,模 块的全局变量就是一个模块对象的属性,仅限于单个模块文件中。
  • 作用范围:当前模块(文件)
a = 1
b = 2


def add():
    # 在外层定义的a ,b 因为作用域是全局所以全局内的函数可以调用
    c = a + b
    print(c)


add()  # 3

(4)Built-in(内置)

  • Built-in(内置):解释器内置的变量,比如int, str等。
  • 作用范围:所有模块(文件)
  • Python中没有块级作用域。
  • 块级作用域:代码块中的变量,比如if、while、for后面的代码

[2]LEGB规则

  • LGEB规则:按照L--->E--->G--->B的顺序查找变量
  • 查找变量时先找局部变量,再找有没有嵌套在外部函数中,再找外面函数中的变量,如果没有外部函数就直接找全局变量,

(1)基于命名空间的常见变量类型

  • 局部变量:
    • 在一个函数体的内部定义的变量
    • 作用域为函数内部
    • 查看局部变量命令:locals()
  • 全局变量
    • 在函数体外部,文件最外层定义的变量
    • 作用域为整个文件内部
    • 查看全局变量命令:globals()
  • 注意:
    • 变量访问规则:从内到外
    • 全局变量和局部变量重名时,采用就近原则

(2)变量的使用规则

  • 创建变量时从上往下创建,搜索变量时从下往上搜索。
  • 创建变量时,下层变量会覆盖上层同名变量,但不会改变上层变量的值,除非使用gloable和nonlocal关键字声明

[3]变量修改

(1)global修改全局 变量

  • 一般全局的变量无法在定义的函数中修改,只能调用
  • 而使用Global关键字声明后就可以在局部中修改
x = 1


def add():
    x = x + 2  # 无法在函数的局部修改这个全局变量
    print(x)


add()  # UnboundLocalError: local variable 'x' referenced before assignment




x = 1


def add():
    global x # 使用global声明后就不会报错
    x = x + 2
    print(x)


add()  # 3 

(2)nonlocal修改外层函数变量

  • 在函数中嵌套函数时,嵌套在里面的函数创建的作用域内一般也是不允许改变外层函数变量的值的
  • 而使用nonlocal声明后就可以使用了
def outer():
    x = 2

    def innner():
        x = x + 2  # 在外层函数定义的x无法在内层函数修改使用报错
        print()

    innner()


outer()  # UnboundLocalError: local variable 'x' referenced before assignment




def outer():
    x = 2

    def innner():
        nonlocal x # 在内层中使用nonlocal声明后就可以修改了
        x = x + 2
        print(x)

    innner()


outer()  # 4