zoukankan      html  css  js  c++  java
  • 🍖名称空间与作用域

    引入

    栈区 / 堆区

    • 栈区 : 存放的是变量名与变量值的内存地址映射关系
    • 堆区 : 存放的是值真正的位置

    栈区和堆区

    一.名称空间

    1.什么是名称空间

    • 存放名字与值绑定关系的地方
    • 名称空间是一个虚拟的概念, 栈区才真实存在

    2.为什么要有名称空间

    • 有了名称空间后就可以在内存的栈区存放相同的名字, 并且不会冲突

    3.名称空间是否有包含关系?

    • 名称空间本质之间是没有包含关系的, 并且相互独立

    名称空间的关系

    二.名称空间的分类(三类)

    1.内置名称空间

    • 存放内置的名字
    • 周期 : 在解释器启动时就产生,解释器关闭则失效
    例如我们常用的内置函数
    print
    len
    input
    

    2.全局名称空间

    • 存放的是顶级的名字 (文件级别的名字)
    • 周期 : 在执行文件时生效,文件运行完毕或文件执行期间被删除则失效
    x = 1      #全局名称空间
    def foo(): #全局名称空间
    	y = 2
    
    注意,"if"下面的定义的变量名都是全局的
    if 1 > 0        
    	z = 3        #全局
    	if 3 > 0: 
    		p = 555  #全局
    

    3.局部名称空间

    • 存放函数内定义的名字
    • 周期 : 在函数调用时临时生效, 函数结束时则失效
    def f()
    	x = 222    #局部名称空间
        
    f()   #函数调用结束失效
    

    4.名称空间的加载顺序

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

    5.名称空间的查找优先级

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

    6.名称空间的销毁顺序

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

    7.名称空间总结与注意事项

    • 重要概念:名称空间的嵌套关系是在函数定义阶段(检测语法)时确定的,与函数调用的位置无关,与函数定义位置有关

    • 三种名称空间必须要有的是 : 内置名称空间, 全局名称空间

    • 查找优先级示例

    从"f2"局部开始找
    x = 3
    def f1():
        x = 2
        def f2():
            x =1
            print(x)
        f2()
    f1()  # 1
    
    将"f2"局部的删除,就往上一层找,找到"f1"
    x = 3
    def f1():
        x = 2
        def f2():
            print(x)
        f2()
    f1()  # 2
    
    再将"f1"里面的删除,于是找到了全局
    x = 3
    def f1():
        def f2():
            print(x)
        f2()
    f1()  # 3
    
    • 函数的嵌套定义示例
    在定义"f2"的之后,有定义了同一级别的"len",所以当打开函数"f2"运行的时候,本着优先级查找就先找到了"222"
    len = 111
    def f1():
        def f2():
            print(len) # 222
    	len = 222
        f2()
    f1()  # 222
    

    三.作用域

    1.什么是作用域

    • 作用域就是根据名称空间的范围和特点进行了归类
    • 查看作用域 : globals( ), locals( )

    2.全局作用域

    • 包含 : 内置名称空间, 全局名称空间
    • 特点 : 全局存活, 全局有效

    3.局部作用域

    • 包含 : 局部名称空间
    • 特点 : 临时存活, 局部有效

    4.L E G B

    • LEGB 代表名字查找顺序 : L--->E--->G--->B
    • locals : 是函数内的名字空间, 包括局部变量和形参
    • enclosing : 外部嵌套的名称空间(闭包中常见面)
    • globals : 全局变量, 函数定义所在模块的名字空间
    • builtins : 内置模块的名字空间

    四.global 与 nonlocal关键字

    1.global 关键字

    • 使用方法 : global x 声明这个 x 是全局变量
    • 针对的是不可变类型的值
    在全局空间定义一个变量"x",函数"foo",在函数内部修改"x"的值
    x = 111
    def foo():
        x = 222
        
    foo()
    print(x)   #111
    #发现并无软用
    
    使用"global"关键字之后
    x = 111
    def foo():
        global x  # 声明下面的"x"属于全局
        x = 222
        
    foo()
    print(x)  #222
    #发现成功了
    

    2.nonlocal 关键字

    • 使用方法 : nonlocal x ,声明外层函数的局部变量
    • 修改该函数外层函数包含的变量名对应的值, 也是针对不可变类型
    • 注意 : 只能在局部名称空间中查找, 先从外部嵌套的函数找, 没找到再往上找, 如果都没找到则报错
    不做任何处理,此函数应该是打印"f2"函数下的"x = 333"
    x = 111
    def f1():
        x = 222
        def f2():
            x = 333
            def f3():
                x = 444
            f3()
            print(x)  #333
        f2()
    f1()  # 333
    
    使用"nonlocal"关键字
    x = 111
    def f1():
        x = 222
        def f2():
            x = 333
            def f3():
                nonlocal x  #将下面的"x = 444"变成了上一层的"x"的值
                x = 444
            f3()
            print(x) 
        f2()
    f1()  # 444
    
    如果外层函数都没有"x"这个值,报错
    x = 111  #并不会去全局修改
    def f1():
        def f2():
            def f3():
                nonlocal x
                x = 444
            f3()
            print(x)
        f2()
    f1()  #报错
    
  • 相关阅读:
    mysql 索引
    springboot + maven jar打包和linux部署
    个人项目———Java实现WordCount
    第四周助教观察记录
    第三周助教工作观察记录
    2019年春-软件工程原理与方法-助教总结
    第十五周助教小结
    第十一周助教小结
    团队作业-设计 成绩汇总
    团队作业选题及需求分析成绩汇总
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14051159.html
Copyright © 2011-2022 走看看