• 函数的名称空间和作用域


    命名空间

       一、什么是python的名称空间

      名称到对象的映射。命名空间是一个字典的实现,键为变量名,值是变量对应的值。各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。

    通俗讲:名称空间就是存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
    原文链接:https://blog.csdn.net/lmseo5hy/article/details/80353099

      二、名称空间的分类

    • 内置名称空间 (Built-in)

       存放着python的内置名称,如内置语言的名称如 len,char 和一些异常的名称 BaseException等,在任何模块都可以被调用,且随着python解释器的启动而产生,关闭而回收,因此它是第一个被加载的名称空间.

    >>> len
    <built-in function len>
    • 全局名称空间

       模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量,伴随着python文件的执行而产生

    • 局部名称空间

       函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量,只有调用函数时才会产生,调用完成时便会被回收

    >>> def func():
    ...     a = 1
    ...
    >>> a
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'a' is not defined
    >>>

      三、命名空间的加载顺序

             内置命名空间(程序运行前加载)-->全局命名空间(程序运行中:从上到下加载)-->局部命名空间(程序运行中:调用时才加载)

      四、命名空间的查找顺序

              局部的命名空间--> 全局命名空间 -> 内置命名空间。

         当这三个命名空间还找不到时,会抛出NameError 异常

    函数的作用域

    作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

    在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。

      一、四种作用域和查找顺序

    • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
    • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
    • G(Global):当前脚本的最外层,比如当前模块的全局变量。
    • B(Built-in): 包含了内建的变量/关键字等。,最后被搜索

      所以查找顺序为 : L –> E –> G –> B

    二、全局变量和局部变量   

    • 全局变量 : 定义在函数外的拥有全局作用域,在整个文件执行过程中都存在,任意位置都能调用(创建类的另说)
    • 局部变量 : 只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    total = 0  # 这是一个全局变量
    
    
    def sum(x, y):
        # 返回2个参数的和."
        total = x + y  # total在这里是局部变量.
        print("函数内是局部变量 : ", total)
        return total
    
    
    sum(1, 2)
    print("函数外是全局变量 : ", total)
    
    
    """
    函数内是局部变量 :  3
    函数外是全局变量 :  0
    """
    View Code

     

    三、global 和 nonlocal 关键字

       当我们想在内部作用域修改外部作用域的变量时,可以使用 global 和 nonlocal 关键字.

    • global 关键字 : 修改全局变量 
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    total = 0  # 这是一个全局变量
    
    
    def sum(x, y):
        # 返回2个参数的和."
        global total
        total = x + y  # total在这里是局部变量.
        print("函数内是局部变量 : ", total)
        return total
    
    
    sum(1, 2)
    print("函数外是全局变量 : ", total)
    
    """
    函数内是局部变量 :  3
    函数外是全局变量 :  3
    """
    View Code
    • nonlocal关键字 : 修改嵌套作用域(enclosing 作用域,外层非全局作用域),如果嵌套了多层函数,nonlocal 会从当前函数的上一层函数开始一层层查找,知道找到最外层,若没找到,则会抛出异常
    def func1():
        # 返回2个参数的和."
        a = 1
        print("start a : ", a)
    
        def func2():
            b = 2
    
            def func3():
                nonlocal a
                a = 3
    
            func3()
    
        func2()
        print("end a : ", a)
    
    func1()
    
    """
    start a :  1
    end a :  3
    """
    View Code

     四、局部变量引用问题

    a = 1
    def test():
        a = a + 1
        print(a)
    
    
    test()
    
    """
    UnboundLocalError: local variable 'a' referenced before assignment
    """

           这是因为在函数内部对变量赋值进行修改后,该变量就会被Python解释器认为是局部变量而非全局变量,当程序执行到a=a+1的时候,因为这条语句是给a赋值,所以a成为了局部变量,那么在执行return        a(或是print a)的时候,因为a这个局部变量还没有定义,自然就会抛出这样的错误。

      解决这个问题可以有以下几种方法:

       1. 在函数内部声明global a

     2.在函数内部重新定义一个a变量

     3.通过函数传递参数

     

  • 相关阅读:
    Debugging Kafka connect
    android O 蓝牙设备默认名称更改
    qualcomm sdm450 tinymix mic record
    QACT 在线调试 Android O
    Android O seLinux 编译错误
    Android seLinux 设置
    高通 fastboot 显示
    高通 双MIC 设置
    高通 添加 cmdline
    高通 mixer_paths.xml 音频配置文件 初始化过程
  • 原文地址:https://www.cnblogs.com/liangweijiang/p/11829545.html
Copyright © 2020-2023  润新知