zoukankan      html  css  js  c++  java
  • 067 名称空间和作用域

    函数内部的函数只能在函数内部调用,不能在函数外部调用,通过接下来的学习你将会知道为什么会出现这种情况。

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f2()  # NameError: name 'f2' is not defined
    

    一、名称空间

    名称空间(name spaces):在内存管理那一章节时,我们曾说到变量的创建其实就是在内存中开辟了一个新的空间。但是我们一直在回避变量名的存储,其实在内存中有一块内存存储变量名与变量间的绑定关系的空间,而这个空间称为名称空间。

    1.1 内置名称空间

    内置名称空间:存放Pyhton解释器自带的名字,如int、float、len

    生命周期:在解释器启动时生效,在解释器关闭时失效

    1.2 全局名称空间

    全局名称空间:除了内置和局部的名字之外,其余都存放在全局名称空间,如下面代码中的x、func、l、z

    生命周期:在文件执行时生效,在文件执行结束后失效

    x = 1
    
    
    def func():
        pass
    
    
    l = [1, 2]
    
    if 3 > 2:
        if 4 > 3:
            z = 3
    

    1.3 局部名称空间

    局部名称空间:用于存放函数调用期间函数体产生的名字,如下面代码的f2

    生命周期:在文件执行时函数调用期间时生效,在函数执行结束后失效

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f1() 
    

    46名称空间与作用域-简单.png?x-oss-process=style/watermark

    1.4 加载顺序

    由于.py文件是由Python解释器打开的,因此一定是在Python解释器中的内置名称空间加载结束后,文件才开始打开,这个时候才会产生全局名称空间,但文件内有某一个函数被调用的时候,才会开始产生局部名称空间,因此名称空间的加载顺序为:内置--》全局--》局部。

    1.5 查找顺序

    由于名称空间是用来存放变量名与值之间的绑定关系的,所以但凡要查找名字,一定是从三者之一找到,查找顺序为:
    从当前的所在位置开始查找,如果当前所在的位置为局部名称空间,则查找顺序为:局部--》全局--》内置。

    x = 1
    y = 2
    len = 100
    
    
    def func():
        y = 3
        len = 1000
        print(f"y: {y}")
        print(f"len: {len}")
        # print(a)  # NameError: name 'a' is not defined
    
    
    func()
    
    y: 3
    len: 1000
    
    x = 1
    
    
    def func():
        print(x)
    
    
    x = 10
    func()
    
    10
    

    二、作用域

    域指的是区域,作用域即作用的区域。

    46名称空间和作用域-地图.jpg?x-oss-process=style/watermark

    2.1 全局作用域

    全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

    # 全局作用域
    x = 1
    
    
    def bar():
        print(x)
    
    
    bar()
    
    1
    

    2.2 局部作用域

    局部作用域:局部有小,临时存储,只包含局部名称空间。

    # 局部作用域
    def f1():
        def f2():
            def f3():
                print(x)
            x = 2
            f3()
        f2()
    
    
    f1()
    
    2
    

    2.3 注意点

    需要注意的是:作用域关系在函数定义阶段就固定死了,与函数的调用无关。

    # 作用域注意点
    x = 1
    
    
    def f1():  # 定义阶段x=1
        print(x)
    
    
    def f2():
        x = 2
        f1()
    
    
    f2()
    
    1
    

    2.4 函数对象+作用域应用

    # 作用域应用
    def f1():
        def inner():
            print('from inner')
        return inner
    
    
    f = f1()  # 把局部定义的函数放在全局之中
    
    
    def bar():
        f()
    
    
    bar()
    
    from inner
    

    三、补充知识点

    3.1 global关键字

    修改全局作用域中的变量。

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            #         global x  # 修改全局
            x = 3
        f2()
    
    
    f1()
    print(x)
    
    1
    
    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            global x  # 修改全局
            x = 3
        f2()
    
    
    f1()
    print(x)
    
    3
    

    3.2 nonlocal关键字

    修改局部作用域中的变量。

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            #         nonlocal x
            x = 3
    
        f2()
        print(x)
    
    
    f1()
    
    2
    
    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            nonlocal x
            x = 3
    
        f2()
        print(x)
    
    
    f1()
    
    3
    

    3.3 注意点

    1. 在局部想要修改全局的可变类型,不需要任何声明,可以直接修改。
    2. 在局部如果想要修改全局的不可变类型,需要借助global声明,声明为全局的变量,即可直接修改。
    lis = []
    
    
    def f1():
        lis.append(1)
    
    
    print(f"调用函数前: {lis}")
    f1()
    print(f"调用函数后: {lis}")
    
    调用函数前: []
    调用函数后: [1]
  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/abdm-989/p/11650085.html
Copyright © 2011-2022 走看看