Python变量作用域及global,nonlocal详解

作用域

作用域就是作用范围,python的作用域是静态的,在代码中变量名被赋值的位置决定了该变量能被访问的范围。即:Python变量的作用域由变量所在源代码中的位置决定。

  1. 作用域的分类
    python中的作用域分4种情况:
    L:local,局部作用域,即函数中定义的变量;
    E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
    G:global,全局变量,就是模块级别定义的变量;
    B:built-in,系统固定模块里面的变量,比如int, bytearray等。

python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量。即常说的 “LEGB原则”

  1. 作用域的产生
    在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if-else、try-except、for等)是不会引入新的作用域的,如下代码【注:以下代码仅作讲解使用】:
if __name__ == "__main__":
    # if-else
    if True:
        x = 1
    else:
        x = 0
    print(x)
    '''
    1
    '''
    # for
    for i in range(10):
        i += 1
    print(i)
    '''
    10
    '''
    # 函数
    def func():
    	y = 1  # 局部变量,仅在函数中生效
    func()
    print(y)
    '''
    程序报错:NameError: name 'y' is not defined
	'''
  1. 局部变量的修改
    Python中不在局部作用域里的变量默认是只读的,如果试图为其绑定一个新的值,Python认为是在当前的局部作用域里创建一个新的变量。如下代码:
	a = 1
    def func2():
        print(a)
        a = 2
        print(a)
    func2()
    '''
   	程序报错:UnboundLocalError: local variable 'a' referenced before assignment
	'''

在第一个print中,使用到了外部作用域a,这样Python会认为后面出现的a就是外部作用域中的a了,再修改就会报错。 如果没使用过这个变量,而直接赋值,会认为是新定义的变量,此时会覆盖外部作用域中变量,如下代码:

	a = 1
    def func3():
        a = 2
        print(a)
    func3()
    '''
    2
    ''''

global关键字

  • 声明一个全局变量。
  • 在局部作用域想要对全局作用域的全局变量【不可变类型】进行修改时,需要用到 global。
  • 对可变数据类型(list,dict,set)可以直接引用而不用通过global。
count = 1
def search():
    global count
    count = 2
search()
print(count)
'''
2
'''

A = [1,2,3]
def change():
    A.append('a')
    print(A)
change()
print(A)
'''
[1, 2, 3, 'a']
[1, 2, 3, 'a']
'''

nonlocal关键字

  • 不能修改全局变量。
  • 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变

注:nonlocal关键字是在Python3之后才有的,优化了Python编程中的闭包问题。

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def do_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        do_nonlocal()
        print(b)
    do_global()
    print(b)
add_b()
'''
10
30
30
42
'''

综合实例练习:

def scope_test():#定义函数
    def do_local():#嵌套函数
        spam = "local spam"#函数里面定义给变量spam赋值
    
    def do_nonlocal():#嵌套函数
        nonlocal spam #嵌套函数内部定义变量spam的作用域
        spam = "nonlocal spam"# 定义变量spam

    def do_global():#嵌套函数
        global spam #在嵌套函数内部定义变量spam作用域
        spam = "global spam"#定义变量spam
		
    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:",spam)
    do_global()
    print("After global assignment:",spam)

scope_test()
print("In global scope:", spam)
'''
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
'''
参考文献

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值