了解python闭包

发布时间 2023-10-06 11:18:31作者: 七落安歌

了解python闭包

1、闭包的作用

当函数调用结束之后,函数内定义的变量都销毁了,但是有时候我们需要函数内的这个变量,每次在这个变量的基础上完成一系列的操作。(即在调用完函数之后,仍然想使用函数内部的变量)

那么我们可以使用闭包来解决这个需求。

闭包的定义:

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

那么如何解释这个官方定义呢

① 有函数嵌套 ② 有引用 ③ 有返回

# ① 有函数嵌套  ② 有引用 ③ 有返回
def outer():
    # 外部函数的变量
    num1 = 10

    # 函数嵌套
    def inner():
        # 引用外部函数的变量
        print(num1)

    # 外部函数返回内部函数
    return inner


fn = outer()  # 相当于fn这个全局变量接收是inner函数名称
fn()  # 调用了inner函数 
  • 为什么num1这个局部变量在函数执行结束之后,内部变量仍然存在

fn = outer() 即将inner的地址赋予了fn,引用计数器+1,而innner函数里面因为print函数,num1的引用计数器+1,所以num1变量仍然存在

疑问:在outer函数里面不也是定义了num1 = 10了吗,这个时候不是num1的引用计数器不是初始化为1呢,是因为在局部作用域中的原因?引用计数器的作用范围是全局作用域?

2、函数在内存中的存储结构

image-20230930201925077

  • 函数名存储在中,函数代码块存储在,函数中的变量的值存储在数据区
def outer():
    return 100


print(outer)  # 并没有执行outer函数,只是返回了outer函数的内存地址
print(outer())  # 添加了圆括号才代表 找到了这个函数并执行内部代码块

image-20230930202927968

3、global关键字和nonlocal关键字

golbal:声明全局变量,代表从这行代码开始,使用的变量都是全局变量,只能在函数的内部使用

问题:在函数嵌套的情况下,内部函数能不能修改外部函数的局部变量?

nonlocal:声明离它最近的外层的局部变量

num = 1


def outer():
    num = 10

    def inner():
        global num  # global关键字
        num = 100

    inner()
    print(f'局部作用域中的num为{num}')  # 10


outer()
print(f'全局作用域中的num为{num}') # 100
  • golbal函数并不能修改局部作用域中的变量
num = 1


def outer():
    num = 10

    def inner():
        nonlocal num  # nonlocal关键字
        num = 100

    inner()
    print(f'局部作用域中的num为{num}') # 100


outer()
print(f'全局作用域中的num为{num}') # 1

4、闭包案例

闭包的关键:在函数执行完,其引用的内部变量不会消失,而是保存下来

def outer():
    result = 0

    def inner(num):
        # 访问离它最近的外层局部变量
        nonlocal result
        result += num
        print(result)

    return inner


fn = outer()
fn(1)  # 1
fn(2)  # 3
fn(3)  # 6