美文网首页
#Python笔记# —— 命名空间(转)

#Python笔记# —— 命名空间(转)

作者: Wakingup88688 | 来源:发表于2017-05-20 01:35 被阅读0次
    好好学习,天天向上,今天是:2017.05.19

    </br>
    Python命名空间、作用域一直没看懂。
    这篇文是网上看到的,写的很好。
    动手再梳理了下,然后再 将内容全部手打了一遍,增加理解。

    原文:Python命名空间的本质 - windlaughing - 博客园 (http://www.cnblogs.com/windlaughing/archive/2013/05/26/3100362.html

    </br>


    思维导图

    </br>
    </br>

    1、定义

    Namespace是名字到对象的一个映射。绝大部分是dict形式,它的见健是那些变量值,值是那些变量的值。

    A namespaceis a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries。
    从某种那意义上来说,一个对象(object)的所有属性(attribute)也构成了一个namespace。在程序执行之间,会有不同的namespace同时存在。对于不同的命名空间内,相同名字的两个变量,这两个变量没有任何关系(互不影响)。

    Python程序中,存在几个可用的命名空间:

    局部命名空间:函数的命名空间,记录函数的变量,包括函数的参数和局部定义的变量

    全局命名空间:模块的命名空间,记录模块的变量,包括函数、类、其它导入的模块、模块级变量和常量

    内置命名空间:任何模块皆可访问,放置着内部函数和异常

    </br>
    </br>

    2、查找顺序

    一行代码要使用一个变量的名字时,会从所有命名空间去寻找,查找顺序如下:

    1)一般情况

    局部命名空间,全局命名空间,内置命名空间,若在这些命名空间找不到相关变量,Python会放弃查找并且引发一个NameError异常

    2)嵌套函数

    现在当前函数(嵌套或者lambda)的命名空间中查找,然后再父类函数命名空间中查找,接着在模块命名空间中查找,最后在内置命名空间中查找。

    实例:

    info="Adress:"
    def func_father(country):
        def func_son(area):
            city="Chengdu"
            print (info+country+city+area)
        city="Beijing" # 此处的city变量,覆盖了父类的city变量
        #调用内部函数
        func_son("Wuhouqu")
    func_father("China")
    

    输出:

    Adress:China Chengdu Wuhouqu
    

    以上实例中,info在全局命名空间中,country在父类函数的命名空间中,city、area在自己函数的命名空间中

    </br>
    </br>

    3、生命周期

    不同Namespace的创建\销毁时间不同,就是说有不一样的生命周期。
    1)内置命名空间在Python解释器启动时自动创建,会一直保留,不会删除
    2)模块的全局命名空间在模块定义被读入时创建,通常一直保存到解释器退出
    3)局部命名空间在函数被调用时创建,返回结果或抛出异常时被删除。所有递归调用的函数都有自己的命名空间

    Python的一个特别之处是:

    a、如果没有global关键字变量声明,一个变量的赋值总在最里层的作用域(innermost)
    b、赋值不会复制数据,只是将命名绑定到对象。删除也是如此,"del y"只是从局部命名空间里删除命名y。(事实上,所有引入新命名的操作都作用于局部作用域)
    c、赋值语句通常会隐式创建一个局部变量,即便在上一层作用域中已经存在该变量的赋值语句

    实例1:

    i=2
    def func2():
        i=i+1
    
    
    func2()
    #错误:UnbondLocalError:local variable 'i' referenced before assignment
    

    由上,Python解释器执行到func3函数时,因为没有在局部作用域中找到对i的赋值(i=i+1无效),所以会抛出一个错误(原文:Python在检查代码前,发现了对i的赋值,并将其添加至局部命名空间中。执行时Python解释器会认为i在局部命名空间中但是没有值,所以产生错误)

    def func3():
        y=123
        del y 
        print y
    
    func3()
    #错误:UnbondLocalError:local variable 'y' referenced before assignment
    #取掉del y后运行正常
    

    </br>
    </br>

    4、命名空间访问

    1)局部命名空间可以用locals() BIF访问
    locals()返回一个键/值的dict,键为变量名字(str形式),值为该变量的实际值
    实例:

    def func1(i,str):
        x=12345
        print (locals())
    
    func1(1,'first')
    

    输出:

    {'str':'first','x':'12345','i':'1'}
    

    2)全局(模块级别)命名空间可以用globals()BIF访问
    实例:

    '''Created on 2013-5-26'''
    
    import copy
    from copy import deepcopy
    
    gstr = "global string"
    
    def func1(i, info):
        x = 12345
       print(locals())
     
    func1(1 , "first")
    
    if __name__ == "__main__":
        print("the current scope's global variables:")
        dictionary=globals()
        print(dictionary)
    

    输出:


    注意:

    a、模块的命名空间不仅包括模块的常量变量,还包括模块中定义的函数和类。此外还包括,任何被导入模块中的东西
    b、内置命名同样放置在一个模块中,被称作builtins
    c、from module import 和import module不同:
    使用import module,模块被导入,但是它仍保持自己的命名空间,所以需要模块名来访问函数或者属性(例如module.function);使用from module import function ,实际上是直接从另一个模块中导入相关属性或函数,因此可以直接访问而不需要知道它们的来源。使用globals函数可以实现。

    3)locals()和globals()区别
    locals是只读的(不能改变),globals不是(可以改变)
    实例:

    def func1(i,info):
        x=12345
        print locals()
        locals()['x']='6789'
        print 'x=',x
    
    y=54321
    func1('1','first')
    globals()['y']='9876'
    print 'y=',y
    

    输出:

    {‘info’:'first','x':'12345','i':'1'}
    x=12345
    y=9876
    

    注意:

    a、locals没有返回局部命名空间,它返回的是一个拷贝。所以对它进行改变,对局部命名空间中的变量值没有影响
    b、globals返回全部实际命名空间,而非拷贝。所以globals返回的dict任何改动都会影响到全局变量(本例中后面的y覆盖掉了前面的y)

    作用域、拷贝之类还没看,后面这一个有一些不太理解,先大概这样。

    相关文章

      网友评论

          本文标题:#Python笔记# —— 命名空间(转)

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