• python nonlocal global 变量作用域


      之前在讨论闭包的时候有提到:

          Python会按LEGB的顺序来搜索变量:

    要说明的是,这里的访问规则只对普通变量有效, 对象属性的规则与这无关(简单地说,访问一个对象的属性与此无关)。
    • L. Local. 局部作用域,即函数中定义的变量(没有用global声明)
    • E. Enclosing. 嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,比如上面的示例中的labmda所访问的x就在其父级函数test的局部作用域里。通常也叫non-local作用域。
    • G. Global(module). 在模块级别定义的全局变量(如果需要在函数内修改它,需要用global声明)
    • B. Built-in. built-in模块里面的变量,比如int, Exception等等

    但此规则有一个重要的限制:

    一个不在局部作用域里的变量默认是只读的,如果试图为其绑定一个新的值, Python认为是在当前的局部作用域里创建一个新的变量
      如果确实要在一个函数里修改全局变量,Python提供了global关键字来声明一个变量是全局变量,声明以后就可以修改其值了。 然而global只能用来修改全局作用域里的变量,对于嵌套函数的情况无能为力,所以计数器的例子在Python 2.x中是无法实现的。
      然而在Python 3中,一个新的关键字nonlocal的产生解决了这个问题
     
    计数器:
    def make_counter():
        count = 0
        def counter():
            nonlocal count
            count += 1
            return count
        return counter
        
    def make_counter_test():
      mc = make_counter()
      print(mc())
      print(mc())
      print(mc())

     也可以使用generator来实现类似的计数器

    def counter_generator():
        count = 0
        while True:
            count += 1
            yield count
        
    def counter_generator_test():
      # below is for python 3.x and works well
      citer = counter_generator().__iter__()
      i = 0
      while(i < 3) : 
        print(citer.__next__())
        i+=1
     
     

    而今天在segmentfault上看到这个问题时却没有及时反应过来:
     

    这段代码不用在函数中声明global x就可以打印出x的值

    x = 20
    def getx():
        print x
    
    getx()

    那请问在哪些情况下必须要使用global声明全局变量?

    以下是一个多线程的python代码片段,其中的x,l都是全局变量,但在threadcode()函数中只声明了global x没有global l。完整的代码是可以成功运行,但是把global x注释掉后就会报错。请问这是为什么,Lock对象比较特殊吗?

    
    
    import threading, time, sys
    x = 50
    l = threading.Lock()
    
    def threadcode():
        global x
        l.acquire()
        print 'Thread %s invoked.' % threading.currentThread().getName()
        try:
            print 'Thread %s running.' % threading.currentThread().getName()
            x = x + 50
            print 'Thread %s set x to %d.' % \
                    (threading.currentThread().getName(), x)
        finally:
            l.release()
    ...
     
    
    
    
    解答:
    对于Python2而言,对于一个全局变量,你的函数里如果只使用到了它的值,而没有对其赋值(指a = XXX这种写法)的话,就不需要声明global。相反,如果你对其赋了值的话,那么你就需要声明global。声明global的话,就表示你是在向一个全局变量赋值,而不是在向一个局部变量赋值。 
    • global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。
    •  nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。
     
     
     
     
     
     
  • 相关阅读:
    (8)route命令(每周一个linux命令系列)
    linux下怎么找到某些命令出自于哪个包
    centos网卡配置详解
    linux下查看系统版本
    (7)awk命令(每周一个linux命令系列)
    centos增加环境变量
    mysql用户操作、权限分配、远程登录设置
    (6)sudo命令详解(每周一个linux命令系列)
    最近的linux工作记录
    (5)ps详解 (每周一个linux命令系列)
  • 原文地址:https://www.cnblogs.com/tangr206/p/3065011.html
Copyright © 2020-2023  润新知