Python 闭包

参考: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]

 

posted @ 2022-08-14 12:21  Picassooo  阅读(63)  评论(0编辑  收藏  举报