Day 17 17.1 python之变量的作用域

一、变量作用域

  • 变量的作用域

    • Python是静态作用域,也就是说Python中,变量的作用域源于它在代码中的位置
    • 在不同的位置,可能有不同的命名空间。命名空间是变量作用域的体现形式
  • python变量作用域一般有4种:

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

1 Local(局部变量)

  • Local(局部变量):暂时的存在,依赖于创建该局部作用域的函数。函数存,则局部变量存,函数亡,则局部变量亡。

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

    • 如下

      # 局部作用域
      def fun():
          b = 2
          print(b)  # 输出2
      
      
      fun()
      print(b)  # 报错
      

2. Enclosed(嵌套)

  • Enclosed(嵌套):一般是在函数中嵌套函数的时候,外层函数的变量作用域。

  • 作用范围:闭包函数

    # Enclosed(嵌套)作用域
    def fun1():
        b = 2
        print("这是fun1打印的:", b)
    
        def fun2():
            print("这是fun2打印的:", b)
    
        return fun2
    
    
    temp = fun1()  # 调用fun1
    temp()  # 调用fun2
    
    
    • 在这里函数fun2里面并没有定义变量b,但是它能够引用外层函数fun1定义的b变量,此时变量b的作用域就是Enclosed

3. Global(全局)

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


def fun1():
    print("这是fun1打印的:", a)


fun1()
print(a)

4. Built-in(内置)

  • Built-in(内置):解释器内置的变量,比如int, str等。
  • 作用范围:所有模块(文件)

Python中没有块级作用域。

块级作用域:代码块中的变量,比如if、while、for后面的代码

二、LEGB规则

  • LGEB规则:按照L--->E--->G--->B的顺序查找变量。
    • 也就是,当不同命名空间具有相同变量名称的变量时,我们首先查找局部变量,如果没有查到,再向全局变量查找。

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

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

2 案例讲解

a = "G全局"  # 定义了一个全局变量G,并把"G全局"赋值给a


def myfunc():
    a = "E局部"  # 定义了一个局部变量a,并把"E局部1"赋值给a

    def inner():
        a = "L局部2"  # 定义了一个局部变量a,并把"L局部2"赋值给a
        print(f"inner打印的a:{a}")

    inner()
    print(f"myfunc打印的a:{a}")


myfunc()
print(f"__main__打印的a:{a}")
  • 结果如下

  • 代码结果分析流程

3 变量的使用规则

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

三、变量的修改

1 global修改全局变量

  • 一般全局变量一经定义后几乎是不用改的,也不允许在局部修改全局变量,除非使用Global关键字声明。

    • 如下

      a = 1
      
      
      def fun1():
          a = a + 2  # 修改全局变量
          print(a)
      
      
      fun1()
      

  • 可以看到,当我们试图在函数fun1创建的局部作用域内改变全局变量a就会报错

    • 但如果在修改之前使用global关键字声明时,就会正常修改外部的全局变量a

    • 如下

      a = 1
      
      
      def fun1():
          global a
          a = a + 2  # 修改全局变量
          print(a)
      
      
      fun1()
      

2 nonlocal修改外层函数变量

  • 在函数中嵌套函数时,嵌套在里面的函数创建的作用域内一般也是不允许改变外层函数变量的值的

  • 除非是nonlocal关键字声明

  • 如下

    # 不使用nonocal声明,修改外层函数变量值
    def fun1():
        a = 1
    
        def fun2():
            a += 2
            print(a)
    
        return fun2
    
    
    temp = fun1()  # 调用fun1
    temp()  # 调用fun2
    

  • 可以看到,报错和在函数内不使用global修改全局变量报的错是一样的

  • 当使用nonlocal声明后再修改就不会报错了

  • 如下

    # 不使用nonocal声明,修改外层函数变量值
    def fun1():
        a = 1
        print(f"我是func1的变量:{a}")
    
        def fun2():
            nonlocal a  # 使用nonocal声明
            a += 2
            print(a)  # 修改后
    
        return fun2
    
    
    temp = fun1()  # 调用fun1
    temp()  # 调用fun2
    

  • 可以看到是正常修改的

posted @ 2023-03-19 09:17  Chimengmeng  阅读(53)  评论(0编辑  收藏  举报