这里介绍Python变量作用域中的global关键字和nonlocal关键字、Closure闭包

global关键字
在内层作用域(比如,函数中),如果对全局变量进行读取/修改, 可通过global关键字来声明该变量是一个全局变量。其实如果只是读取变量不修改的话,当内层作用域找不到变量定义时,其会到外层作用域去找。需要注意的是,如果在内层作用域定义了一个与全局变量同名的局部变量,则在内层作用域操作的是局部变量,而不是全局变量
print("----------- 变量作用域 -----------------------")
# 全局变量
b = 1000
def f1(a):
print(f"[f1]: a -->> {a}")
# 只读不修改时,当内层作用域找不到变量b时,其会到外层作用域去找
print(f"[f1]: b -->> {b}")
def f2(a):
print(f"[f2]: a -->> {a}")
# 内层作用域定义的变量(即使其与全局变量同名)为局部变量
b = 22
print(f"[f2]: b -->> {b}")
def f3(a):
# 如果确实想在内层作用域中对全局变量进行修改, 可通过global关键字来声明变量是一个全局变量
global b
print(f"[f3]: a -->> {a}")
print(f"[f3]: b -->> {b}")
b = 500
print(f"[f3]: after modify, b -->> {b}")
print("n--------------- Test f1 函数 ---------------------")
f1(1.1)
print("n--------------- Test f2 函数 ---------------------")
f2(2.2)
# 全局变量b的值未变,说明f2中修改的确实是局部变量
print(f"b --->> {b}")
print("n--------------- Test f3 函数 ---------------------")
f3(3.3)
# 全局变量b的值变了,说明f3中修改的确实是全局变量
print(f"b --->> {b}")

当我们对全局变量进行修改时,如果不使用global关键字来声明该变量是一个全局变量,即会因为找不到变量定义而报错
num = 996
def func3():
# 对全局变量进行修改时,需要通过 global关键字来声明该变量是一个全局变量
# 否则即会因为找不到变量定义而报错
num += 50000
print(f"num -->> {num}")
func3()

Closure闭包
在外层函数中嵌套定义一个内层函数时,一方面:在内层函数定义中使用了外层函数中定义的变量;另一方面,外层函数直接返回了内层函数,使得该内层函数可以在其定义环境外被执行。这样的一个内层函数我们称之为Closure闭包
title = "闭包定义"
print(f"------------ {title} -------------------")
def f1():
name = "Aaron"
# 这里内层函数f2使用了外层函数f1的变量name,此时就产生了闭包。其中f2就是一个闭包函数
def f2():
msg = f"{name}: Hello ..."
print(msg)
print(f"f2 函数: {f2}")
return f2
f2_new = f1()
# f2_new变量指向的就是f2函数
print(f"f2_new变量 --->>> {f2_new}")
print("函数f2中局部变量的名称:", f2_new.__code__.co_varnames)
print("函数f2中自由变量的名称:", f2_new.__code__.co_freevars)
# 从下不难看出,对于闭包函数f2而言,
# 它会保留 定义f2函数时对name变量的绑定,这样当我们在f1函数的外面调用f2函数。
# 虽然f1函数的作用域已经不存在了,但是仍能使用name变量
for cell in f2_new.__closure__:
print("函数f2中自由变量对应的值:", cell.cell_contents)
# 在f1函数外面调用f2函数,依然可以访问name变量
f2_new()

nonlocal关键字
在Python中,如果内层函数需要访问外层函数的变量,可使用nonlocal关键字来进行声明
def make_averager():
count = 0
sum = 0
def avg(num):
# 由于在函数中变量进行修改,Python解释器会将其视为局部变量
# 为解决此问题,Python 3中引入了nonlocal关键字
# 表明其不是局部变量, 而是外层函数的变量
nonlocal count, sum
count += 1
sum += num
return sum / count
return avg
avg = make_averager()
print(f"计算平均值: {avg(20)}")
print(f"计算平均值: {avg(10)}")
print(f"计算平均值: {avg(3)}")

参考文献
-
Python编程·第3版:从入门到实践 Eric Matthes著 -
Python基础教程·第3版 Magnus Lie Hetland著 -
流畅的Python·第1版 Luciano Ramalho著
原文始发于微信公众号(青灯抽丝):Python之变量作用域、Closure闭包
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/296367.html