zoukankan      html  css  js  c++  java
  • Python作用域

    转自: https://blog.csdn.net/wentyoon/article/details/53301594

    python作用域
    LEGB原则
    python中作用域有四种:

    L (Local) 局部作用域 
    E (Enclosing) 闭包函数外的函数中 
    G (Global) 全局作用域 
    B (Built-in) 内建作用域
    
    

    python按照LEGB原则搜索变量,即优先级L>E>G>B。

    #dir 为python内建函数
    dir = 1 # Global
    def outer():
        dir = 2  # Enclosing
        def inner():
            dir = 3 # Local
            return dir
        return inner
    
    print outer()() # 输出3
    
    

    作用域(Scope)和命名空间(NameSpace)
    def/lambda会创建新的作用域,生成器表达式都有引入新的作用域,class的定义没有作用域,只是创建一个隔离的命名空间。在Python中,scope是由namespace按特定的层级结构组合起来的。scope一定是namespace,但namespace不一定是scope。命名空间跟作用域的区别是,它不能在里面再嵌套其他作用域。下面看两个例子。
    例1

    a = 1
    def test():
        a += 1
        a = 2
    
    test() #异常
    
    

    UnboundLocalError: local variable ‘a’ referenced before assignment。这是因为解释器看到a+=1时,按照LEGB优先在Local中找到了a的声明,执行时先a+=1在a=2声明之前,所有抛出异常。

    例2

    class A(object):
        x = 2
        gen = (x*i for i in xrange(5))
    
    if __name__ == "__main__":
        a = A()
        print list(a.gen)#异常
    
    

    上面的代码会抛出异常:NameError: global name ‘x’ is not defined。这是因为gen = (x for _ in xrange(5)是生成器,会产生新的作用域。而classA 中并不产生作用域。按照LEGB原则,不能找到x的定义,所以抛出异常。解决这个问题有几种方案。
    1,将x定义为全局变量,这样可以解决异常,但是可能违背了类的逻辑。
    2,将生成器表达式改为列表表达式。

    gen = [x*i for i in xrange(5)]
    
    

    在python2中,列表表达式不产生新的作用域,所以不会抛出异常。但是在python3中仍有异常。
    3,用A.x的方式访问类属性。

    gen = (A.x*i for i in xrange(5))
    
    

    4,引入lambda函数,将class命名空间的x作为变量传入到匿名函数中。

    gen = (lambda x: (x*i for i in xrange(5)))(x)
    
    

    这个问题可以理解为class不能产生作用域导致的,在函数中就没有这个问题。

    def test():
        x = 2
        gen = (i * x for i in xrange(5))
        return gen
    
    gen = test()
    print list(gen)#输出[0, 2, 4, 6, 8]
    
  • 相关阅读:
    【Educational Codeforces Round 101 (Rated for Div. 2) C】Building a Fence
    【Codeforces Round #698 (Div. 2) C】Nezzar and Symmetric Array
    【Codeforces Round #696 (Div. 2) D】Cleaning
    【Codeforces Round #696 (Div. 2) C】Array Destruction
    【Educational Codeforces Round 102 D】Program
    【Educational Codeforces Round 102 C】No More Inversions
    【Good Bye 2020 G】Song of the Sirens
    【Good Bye 2020 F】Euclid's nightmare
    使用mobx入门
    requestAnimationFrame 控制速度模拟setinterval
  • 原文地址:https://www.cnblogs.com/nyist-xsk/p/9359286.html
Copyright © 2011-2022 走看看