• python进阶之命名空间与作用域


     

    命名空间 Namespace

    Namespace命名空间,命名空间是一个字典(dictionary),它的键就是变量名,它的值就是那些变量的值。命名空间的一大作用是避免名字冲突。 

    python使用命名空间记录变量的轨迹。python中有三个命名空间:

     

    命名空间

    名称

    记录数据

    函数的命名空间

    局部命名空间

    (local namespace)

    记录了函数的参数和局部定义的变量

    模块的命名空间

    全局命名空间

    (global namespace)

    记录了模块的变量,包括函数,类,其他导入的模块,模块级的变量和常量

    内置命名空间

    内置命名空间

    (build-in)

    存放内置的函数和异常,例如:abs()

     

     

     

     

     

     

     

     

     

     

    内置函数 locals(),返回当前函数的局部命名空间

    x = 100
    
    def fun():
        a = 1
        b = 2
        print locals()
        return a+b
    
    fun()
    结果: {'a': 1, 'b': 2}

      

     

    内置函数globals(),返回当前模块的全局命名空间

    x = 100
    
    def fun():
        a = 1
        b = 2
        print locals()
        return a+b
    
     
    fun()
    print globals()
    

    结果: {'a': 1, 'b': 2}
    {'__builtins__': <module '__builtin__' (built-in)>, '__file__': 'locals.py', '__package__': None, 'x': 100, 'fun': <function fun at 0x7fb18df93668>, '__name__': '__main__', '__doc__': None}

      

      

    命名空间查找顺序

    当代码要使用变量x的值时,Python解释器回到所有可用的命名空间去查找变量,顺序:

    1. 局部命名空间:当前函数或者类的方法。如果函数定义了一个局部变量x,解释器使用它,停止搜索。
    2. 在父函数或嵌套的命名空间中搜索
    3. 全局命名空间,搜索当前的模块,如果模块定义了名为x的变量,函数,或者类,解释器使用它。
    4. 内置命名空间:对每个模块都是全局的,作为最后的尝试,python将假设x为内置函数或变量。
    5. 如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,NameError: name 'aa' is not defined。

     

    命名空间的生命周期

    1. 内置命名空间,python解释器启动时创建,退出时销毁
    2. 全局命名空间,模块定义被解释器读入时创建,解释器退出时销毁
    3. 局部命名空间,函数调用时创建,函数返回或者异常时销毁
    def fun():
        a = 1
    
    fun()
    print a
    
    Traceback (most recent call last):
    File "find_namespce.py", line 6, in <module>
        print a
    NameError: name 'a' is not defined
    

      

    作用域

    作用域针对变量而言,指申明了变量在程序里的可应用范围。只有函数,类,模块会产生作用域,代码块不会产生作用域。例如for循环,if判断都不产生作用域。

     

    作用域可以划分成4类:

    1. 局部作用域
    2. 嵌套作用域
    3. 全局作用域
    4. 内建作用域

     

    作用域链

    python中作用域链,变量会由内到外去找,先去自己的作用域找,自己没有在去上级去找,一直到找不到报错。

    特性:

    函数未执行之前,作用域已经形成,作用域链也生成了

    name = "lzl"
    
    def f1():
        print(name)
    
    def f2():
        name = "eric"
        f1()
    f2()

      

    这里有解释

    #在f2中执行f1时,f1的作用域链已经形成,向上级找,name为lzl。

     

     

    全局变量和局部变量

    全局变量:所有函数之外定义的变量

    局部变量:函数内部定义的变量 或者类,模块里的变量

     

    全局变量和局部变量使用:

    函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义了一个局部变量,不管全局域中有没有该变量名,函数中使用的将是局部变量。

    (即声明了一个新的局部变量。如果这个变量名字和全部变量名字相同,那么局部变量名字会覆盖全局变量名字。)

    b = 2
    
    def fun():
    
        a = 1
        b = 10
        print locals()
        print a
        print b
    
     
    
    fun()
    print globals()

    {'a': 1, 'b': 10} 1 10 {'b': 2, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'find_namespce.py', '__package__': None, 'fun': <function fun at 0x7fb7bda1d668>, '__name__': '__main__', '__doc__': None}

      

    局部变量如何使用全局变量:

    [关键字 global]

    #[demo1]
    
    Num = 100  
    def func():  
        global Num  #声明这个Num是全局。如果全局变量已经有这个Num变量那就是指的它 如果全局没这个Num那就新定义一个全局变量。
        Num  = 200  #凡是在函数内部Num始终是指全局变量。这里不可能有个局部变量叫Num的。
        print(Num )  
    
    func()  
    print(Num ) #输出200 说明修改的就是全局变量啊
    

      

     

    #[demo2]
    
    def func():  
        global Num  #声明这个Num是全局的哦。而且恰恰是此时没有一个全局变量是Num。那么如果全局没这个Num那就新定义一个Num的全局变量。
        Num  = 200  
        print(Num )  
    
    func()  
    print(Num ) #输出200 说明新定义了一个全局变量Num

    如果不是明显要局部变量和全局变量互相操作能不纠缠就不纠缠。也就是定义变量名字的时候 要严格规范。按照开发规范来定义名字。全局大写或者加上“_”开头,这是避免不必要问题的根本消灭问题。如果实在是场景需求 局部要操作修改赋值全局变量。那就使用global。

  • 相关阅读:
    js 中读取JSON的方法探讨
    git 教程 git.oschina.net
    JS实现页面跳转重定向的几种方式
    AngularJs 学习
    firebug js版
    emmt html生成
    idea sass scss配置
    关于idea激活
    sublime text There are no packages 解决!
    js监听滚动条事件
  • 原文地址:https://www.cnblogs.com/goldsunshine/p/10948475.html
Copyright © 2020-2023  润新知