美文网首页
Python基础(十四): 函数作用域

Python基础(十四): 函数作用域

作者: 伯wen | 来源:发表于2018-03-05 00:27 被阅读10次

    一、基本概念

    1、变量的作用域
    • 变量的作用范围: 可操作范围

    • Python是静态作用域, 也就是说在Python中, 变量的作用域源于它在代码中的位置, 在不同的位置, 可能有不同的命名空间

    2、命名空间
    • 命名空间是作用域的体现形式

    • 表示变量不同的具体的操作范围

    3、Python-LEGB
    • L-Local: 函数内的命名空间
      • 作用范围: 当前整个函数体
      def test():
          a = 10
          print(a)
      test()      # 打印: 10
      
      • a的作用范围只在test函数中
    • E-Enclosing function locals: 外部嵌套函数的命名空间
      • 作用范围: 闭包函数
      def test():
          a = 10
          def inner():
              print(a)
          inner()
      test()      # 打印: 10
      
      • a的作用域, 在整个闭包函数test
    • G-Global: 全局命名空间
      • 作用范围: 当前模块(文件)
      a = 10
      def test():
          print(a)
      test()  # 打印: 10
      
      • a的作用域, 在整个模块当中, 可以理解为当前文件
    • B-Builtin: 内建模块命名空间
      • 作用范围: 所有模块(文件)
      print("aaa")
      
      • print函数, 在所有文件中都可以使用
    • 注意:
      • Python中没哟快级作用域
      • 快级作用域: 代码块中, 比如 if while for 后的代码块
    • LEGB规则: 会按照 L -> E -> G -> B 的顺序进行查找

    二、基础命名空间的常见变量类型

    1、局部变量

    • 在一个函数内部定义的变量

    • 作用域为函数内部

    • 查看局部变量, 可以使用函数locals()

    2、全局变量

    • 在函数外部, 文件最外层定义的变量

    • 作用域为整个文件内部

    • 查看全部变量, 可以使用函数globals()

    3、注意点

    • 访问原则:

      • 从内到外
    • 结构规范:

      • 全局变量
      • 函数定义: 使用和修改
      • 后续代码
    • 全局变量和局部变量重名

      • 获取: 就近原则
      • 修改: global 全部变量
    • 命名规范:

      • 全局变量: g_xxx

    三、举例

    1、闭包
    • 代码
    def test()
        a = 10
        def inner():
            print(a)
    
    • a的作用域在整个闭包函数test内, 所以inner中可以访问
    def test()
        a = 10
        def inner():
            a = 5
            print(a)
    
    • 此时在inner中, 定义了一个变量a, 此时inner中的atest中的a, 属于两个不同的变量
    • innerprint(a), 会根据就近原则找到变量a = 5
    • 如果想要inner中的a不是新定义的变量, 而是test中的a进行重新赋值, 需要用到关键字nonlocal
    def test()
        a = 10
        def inner():
            nonlocal a
            a = 5
            print(a)
        print(a)
        inner()
        print(a)
    test()
    
    # 打印结果:
    10
    5
    5
    
    • 此时, 使用nonlocal修饰a, 则说明inner中的变量a不是新定义的, 而是test中的, 此时对a赋值, 会修改test中a的值
    2、函数中修改全部变量的值
    a = 10
    def test():
        a = 5
        print(a)
    print(a)
    test()
    print(a)
    
    # 打印结果:
    10
    5
    10
    
    • 第一次打印, a = 10
    • 第二次打印, 执行了test函数, 在内部新定义了一个变量a = 5
    • 第三次打印, a = 10, 此时打印与第一次相同, 因为在test中没有对全局变量a进行赋值, 而是新定义了一个变量
    • 在函数内部修改全部变量, 与闭包有些类似, 只不过闭包中用的关键字是nonlocal, 而修改全局变量, 则需要使用关键字global
    a = 10
    def test():
        global a
        a = 5
        print(a)
    print(a)
    test()
    print(a)
    
    # 打印结果:
    10
    5
    5
    
    • 由于test中的a使用了global关键字进行修饰, 此时a = 5不在是定义新的变量, 而是对全局变量进行赋值操作
    3、函数中的变量, 只有在调用时才去查找
    a = 10
    def test():
        print(a)
        print(b)
        
    b = 15
    test()
    
    # 打印结果:
    10
    15
    
    • 上述代码中, btest后定义, 而在test中使用了b
    • 之所以代码正常运行, 是因为只有在test()时, test函数被调用了, 才去查找b的值, 而此时b = 15已经被定义, 所以不会出错

    相关文章

      网友评论

          本文标题:Python基础(十四): 函数作用域

          本文链接:https://www.haomeiwen.com/subject/xdxffftx.html