参考:python 闭包理解 (推荐)
每个函数都有一个叫做 __closure__ 的属性,一般情况下这个属性为None。
但如果在一个外函数中定义了一个内函数,且内函数里使用了外函数的变量,那这个内函数的 __closure__就不再是None,而是有了真实内容,这些内容是所有外函数的变量的集合,也就是闭包。在内函数中使用外函数的变量时,实际上就是从这个 __closure__中取变量的。
示例1:
def f1(): b = 1 def f2(): c = b * 3 print('c: ', c) f2() if __name__ == '__main__': f1() # 输出: # c: 3
需要注意的是,在内函数中,不能直接对外函数的变量进行赋值,示例如下:
def f1(): b = 1 def f2(): b = 2 # 这个b会被认为是内函数f2的局部变量,和外函数f1的b没有关系 print('内函数 b: ', b) f2() print('外函数 b: ', b) if __name__ == '__main__': f1() # 输出: # 内函数 b: 2 # 外函数 b: 1
因为在python3中,不能直接对外部变量进行写,如果直接写,它会认为你在重新定义一个内部函数的局部变量,并在接下来的访问中隐藏对外部同名变量的访问。如果确实需要写外部变量,需要先在使用前声明,使用nonlocal关键字,上面例子可以修改下:
def f1(): b = 1 def f2(): nonlocal b b = 2 # 这个b是从__closure__中读取的,即是外函数f1的b print('内函数 b: ', b) f2() print('外函数 b: ', b) if __name__ == '__main__': f1() # 输出: # 内函数 b: 2 # 外函数 b: 2
如果外函数的变量是列表,可以直接在内函数进行操作:
def f1(): b = [] def f2(): b.append(1) print('内函数 b: ', b) f2() print('外函数 b: ', b) if __name__ == '__main__': f1() # 输出: # 内函数 b: [1] # 外函数 b: [1]