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

    1.作用域和名字空间由来及解释定义     

    Python有一个核心概念是名字空间(namespace),namespace是一个name到object 的映射关系,Python有很多namespace,因此,在代码中如果碰到一个标志符(name),需要有一个规则来决定去哪个namespace查找——这就是LEGB。

    LEGB决定了name的查找顺序:locals -> enclosing function -> globals -> __builtins__

    • locals 是函数内的名字空间,包括局部变量和形参;
    • enclosing 外部嵌套函数的名字空间(闭包中常见);
    • globals 全局变量,函数定义所在模块的名字空间;
    • builtins 内置模块的名字空间;   

    所以,在 Python 中检索一个变量的时候,优先到 locals 里面来检索,检索不到的情况下会检索 enclosing ,enclosing 没有则到 globals 全局变量里面检索,最后是到 builtins 里面来检索。

    当然,因为 builtins 的特殊性,我们可以直接在 builtins 里面添加变量,这样就可以在任意模块中访问变量,不过这种方法太过于变态,不推荐这么做。

    LGB规则(闭包是一种特殊的作用域,暂不考虑)与name space加载的顺序相反,Python解释器初始化的时候会先加载built-in namespace,它由__builtins__模块的名字构成,随后加载global namespace。 如果在执行期间调用了一个函数,那么将创建局部名字空间。

    Python中一切都是object,包括function、module、class、package,这些objects都有在内存中真真正正的存在。每个object都有自己的namespace,每个object的namespace是独立的,可以通过object.name的方式访问object的namespace中的name,因此,不同的namespace中可以使用相同的name,而不会引发混淆。namespace是动态创建的,每一个namespace的生存时间也不一样。例如,一个module的namespace是它被import的时候创建的。而function被调用时,创建其local namespace,调用结束或抛出exception的时候, 该local namespace将被删除。

      

    locals( )和globals( )分别返回dictionary结构的global namespace和local namespace,例如:

    复制代码
    a = 3
    
    def proc():
        a = 3
        print(locals())
        print(globals())
        
    proc()
    复制代码

    可以看见,局部作用域和全局作用域都有变量a,但它们不是同一个对象。

    注意:还有一个特殊的module,一进入python解释器,就建立了一个module,这个module的namespace就是global namespace,一个全局唯一的namespace。这个module的一个内部的attribute,__name__等于__main__。如果模块是被导入的,__name__的值为模块的名字;如果模块是被直接执行的,__name__的值为’__main__’。

    scope(作用域):用unqualified reference name(即与object.name相比,没有object的前缀)就可以直接找到name所指的对象。 LGB规则用scope的概念来解释就是:在任何代码执行的时候,都至少有3个scope,从内到外一次查找一个unqualified reference name。

    函数体内的局部变量和全局变量如果重名,全局变量不可见(被局部变量覆盖)。

    复制代码
    x = 50
    
    def func(x):
        print('x=', x)  #50
        x = 2           
        print('x=', x)  #2
    
    func(x)
    
    print('x=', x)      #50

    一个更复杂的例子:

    j, k = 1, 2
     
    def proc1():
        j, k = 3, 4
        print "j==%d and k=%d" %(j,k)
        k = 5

    def proc2():
        j = 6
        proc1()
        print "j==%d and k=%d" %(j,k)

    k = 7
    proc1()
    print "j==%d and k=%d" %(j,k)

    j = 8
    proc2()
    print "j==%d and k=%d" %(j,k)

    当在函数中需要修改全局变量时,如果没有global关键字则会出错

    复制代码
    x = 50
    
    def run():
        print x
        x = 2  
    
    run()
    复制代码

    报错为:UnboundLocalError: local variable 'x' referenced before assignment

    加上global关键字以后则OK

    复制代码
    x = 50
    
    def run():
        global x
        x = 2  
    
    run()
    print x     #2

    end

  • 相关阅读:
    C#操作XML配置文件
    Git详细命令
    ng : File C:UsersaronAppDataRoaming pm g.ps1 cannot be loaded because running
    Abstract抽象类 && Interface接口
    Markdown基本使用
    Scrapy基本使用
    request取值相关
    轮询与长轮询
    爬虫
    Flask相关组件及应用
  • 原文地址:https://www.cnblogs.com/hanxiaofeicf/p/7028001.html
Copyright © 2011-2022 走看看