python中global 和 nonlocal 的作用域

in #python7 years ago (edited)

最近在学习python,在这里记录学习中的问题

global

global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。

In [5]: gcount = 0

In [6]: def global_test():
   ...:     gcount+=1
   ...:     print (gcount)
   ...:     

In [7]: global_test()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-7-86f3510ae66b> in <module>()
----> 1 global_test()

<ipython-input-6-ef97fb6917fb> in global_test()
      1 def global_test():
----> 2     gcount+=1
      3     print (gcount)
      4 

UnboundLocalError: local variable 'gcount' referenced before assignment

第一行定义了一个全局变量,(可以省略global关键字)。
在global_test 函数中程序会因为“如果内部函数有引用外部函数的同名变量或者全局变量,并且对这个变量有修改.那么python会认为它是一个局部变量,又因为函数中没有gcount的定义和赋值,所以报错。

声明全局变量。

如果在局部要对全局变量修改,需要在局部也要先声明该全局变量

In [8]: gcount = 0

In [9]: def global_test():
   ...:     global gcount
   ...:     gcount+=1
   ...:     print (gcount)
   ...:     

In [10]: global_test()
1

如果在函数中声明 gcount 是全局变量,即可对其进行修改。 正确输出 1 。

如果不修改全局变量

在局部如果不声明全局变量,并且不修改全局变量。则可以正常使用全局变量

In [11]: gcount = 0

In [12]: def global_test():
    ...:     print (gcount)
    ...:     
    ...:     

In [13]: global_test()
0

如果在局部不修改全局变量,程序正确输出 0 。

nonlocal关键字

用来在函数或其他作用域中使用外层(非全局)变量。

In [14]: def make_counter():
    ...:     count = 0
    ...:     def counter():
    ...:         nonlocal count
    ...:         count += 1
    ...:         return count
    ...:     return counter
    ...: 

In [15]: def make_counter_test():
    ...:     mc = make_counter()
    ...:     print(mc())
    ...:     print(mc())
    ...:     print(mc())
    ...:     


In [16]: make_counter_test()
1
2
3

测试

In [35]: def scope_test():
    ...:     spam = "test spam"
    ...:     def do_local():
    ...:         spam = 'local spam'
    ...:     def do_nonlocal():
    ...:         nonlocal  spam
    ...:         spam = 'nonlocal spam'
    ...:     def do_global():
    ...:         global spam
    ...:         spam = 'global spam'
    ...:     do_local()
    ...:     print('after local assignmane:', spam)
    ...:     do_nonlocal()
    ...:     print('after nonlocal assignment:', spam)
    ...:     do_global()
    ...:     print('after global assignment:', spam)
    ...:     

In [36]: scope_test()
after local assignmane: test spam
after nonlocal assignment: nonlocal spam
after global assignment: nonlocal spam

In [37]: print('in global scope:', spam)
in global scope: global spam