python函数闭包概念

作者:

文章目录
  • 函数是实现特定功能的代码段的封装,在需要时可以多次调用函数来实现该功能。 Python如下定义一个函数,我们可以通过任何变量来将此函数进行赋值操作,如下: def greet(): return “Hello!” # 将方法赋给变量(无括号,得到方法对象) greet_func = greet # 调用存储在变量中的方法 print(greet_func()) print(type(greet_func)) # 输出 greet_func 的类型,由于 greet_func 指向的是 greet 函数对象,所以输出结果为 <class ‘function’> print(type(greet_func())) # 先调用 greet_func 所指向的函数,得到返回值 “Hello!”,然后输出该返回值的类型,结果为 <class ‘str’>。 # 有括号,直接调用方法并将结果赋给变量 greet_result = greet() print(greet_result) print(type(greet_result)) # 输出 greet_result 的类型,由于它存储的是字符串,所以输出结果为 <class ‘str’> print(type(greet_result())) # 报错greet_result 存储的是字符串 “Hello!”,而不是函数对象,所以不能像调用函数一样在它后面加上括号 () 在 Python 中,函数是一等公民,这意味着函数可以像其他对象(如整数、字符串等)一样被赋值给变量。这里将 greet 函数对象赋值给了变量 greet_func。此时 greet_func 实际上指向的是 greet 函数本身,而不是函数的返回值;而 greet_result = greet() 是先调用 greet 方法,然后把返回值赋给 greet_result 变量。
  • 目录
    • 一、函数
    • 二、闭包
      • 2.1 概念
      • 2.2 闭包的应用场景
      • 2.3 代码实例
      • 实例 2:带参数的闭包
      • 实例 3:闭包用于数据封装和隐藏

    函数是实现特定功能的代码段的封装,在需要时可以多次调用函数来实现该功能。

    Python如下定义一个函数,我们可以通过任何变量来将此函数进行赋值操作,如下:

    def greet():
        return "Hello!"
    # 将方法赋给变量(无括号,得到方法对象)
    greet_func = greet
    # 调用存储在变量中的方法
    print(greet_func())
    print(type(greet_func))   # 输出 greet_func 的类型,由于 greet_func 指向的是 greet 函数对象,所以输出结果为 <class 'function'>
    print(type(greet_func())) # 先调用 greet_func 所指向的函数,得到返回值 "Hello!",然后输出该返回值的类型,结果为 <class 'str'>。
    # 有括号,直接调用方法并将结果赋给变量
    greet_result = greet() 
    print(greet_result)
    print(type(greet_result))  # 输出 greet_result 的类型,由于它存储的是字符串,所以输出结果为 <class 'str'>
    print(type(greet_result())) # 报错greet_result 存储的是字符串 "Hello!",而不是函数对象,所以不能像调用函数一样在它后面加上括号 ()

    在 Python 中,函数是一等公民,这意味着函数可以像其他对象(如整数、字符串等)一样被赋值给变量。这里将 greet 函数对象赋值给了变量 greet_func。此时 greet_func 实际上指向的是 greet 函数本身,而不是函数的返回值;而 greet_result = greet() 是先调用 greet 方法,然后把返回值赋给 greet_result 变量。

    在 Python 中,闭包(Closure)是一种特殊的函数,它由一个函数和该函数所引用的外部作用域中的变量组成。即使外部函数已经执行完毕,其局部变量的生命周期也会因闭包的存在而得以延长,闭包可以继续访问这些变量。

    简单来说,闭包允许函数访问并操作其定义所在的外部作用域中的变量,即使该外部作用域已经结束。

    构成闭包需要满足以下三个条件:

    • 存在一个嵌套函数,即在一个函数内部定义另一个函数。
    • 嵌套函数引用了外部函数的局部变量。
    • 外部函数返回嵌套函数。

    • 数据封装和隐藏:可以将数据隐藏在闭包内部,只通过闭包提供的接口来访问和修改数据。
    • 实现回调函数:在事件驱动编程中,闭包可以作为回调函数,保存一些上下文信息。
    • 实现装饰器:装饰器是闭包的一种常见应用,用于在不修改原函数代码的情况下,为函数添加额外的功能。

    实例 1:简单计数器闭包

    def outer_function():
        # 外部函数的局部变量
        count = 0
        def inner_function():
            # 声明count为外部函数的局部变量, 以便可以修改它
            nonlocal count
            count = count + 1
            return count
        return inner_function
    # 创建闭包实例
    counter = outer_function()
    # 多次调用闭包
    print(counter())  # 输出: 1
    print(counter())  # 输出: 2
    print(counter())  # 输出: 3

    代码解释

    • outer_function是外部函数,它定义了局部变量count并初始化为 0。
    • inner_function是嵌套在outer_function内部的函数,它引用了外部函数的 count 变量,并对其进行加 1 操作。nonlocal 关键字用于告诉 Python,count 变量不是当前inner_function的局部变量,而是外部函数的局部变量,这样才能在内部函数中修改它。
    • outer_function 返回了 inner_function,形成了闭包。当调用 outer_function() 时,会返回inner_function 的引用并赋值给counter。每次调用 counter() 时,count变量的值都会在之前的基础上增加 1,说明 count 变量的状态被闭包保存下来了。

    def multiplier(factor):
        print("++++++", factor)
        def multiply_by_factor(number):
            print("++++++", number)
            return number * factor
        return multiply_by_factor
    # 创建一个乘以 3 的闭包
    triple = multiplier(3)
    # 调用 __closure__ 内置方法可以查看到两个内存地址,结果返回cell就是闭包,None 则不是闭包,可以看出来其实这是一个元组类型,使用[0].cell_contents可以得到闭合数值,也就闭包所需要的环境变量。
    print(triple.__closure__)
    # 闭包所需要的环境变量
    print(triple.__closure__[0].cell_contents)
    print(triple.__class__)
    print(triple(5))

    代码解释

    • multiplier 是外部函数,它接受一个参数 factor
    • multiply_by_factor 是嵌套函数,它接受一个参数 number,并返回 number 乘以 factor 的结果。
    • multiplier 返回 multiply_by_factor,形成闭包。调用 multiplier(2) 会返回一个闭包,该闭包会将传入的数字乘以 2,将其赋值给 double。同理,multiplier(3) 返回的闭包会将传入的数字乘以 3,赋值给 triple

    运行结果:

    def account(initial_balance):
        balance = initial_balance
        def deposit(amount):
            nonlocal balance
            balance = balance + amount
            return balance
        def withdraw(amount):
            nonlocal balance
            if amount <= balance:
                balance = balance - amount
                return balance
            else:
                print("余额不足")
                return balance
        def get_balance():
            return balance
        return deposit, withdraw, get_balance
    # 创建账户闭包
    deposited, withdrawed, get_balanceed = account(1000)
    # 存款操作
    print(deposited(500))  # 输出: 1500
    # 取款操作
    print(withdrawed(200))  # 输出: 1300
    # 查询余额
    print(get_balanceed())  # 输出: 1300

    代码解释

    • account 是外部函数,它接受一个初始余额 initial_balance 并将其赋值给局部变量 balance
    • deposit、withdrawget_balance 是嵌套函数, 它们 都引用了外 部函数balance 变量。deposit 函数用于存款,withdraw 函数用于取款,get_balance 函数用于查询余额。
    • account 函数返回这三个嵌套函数,形成闭包。通过调用account(1000) 创建了一个账户闭包,并将返回的三个函数分别赋值给 depositedwithdraweget_balanceed。可以通过调用这些函数来进行账户的存款、取款和查询余额操作, 而 balance 变量被封装在闭包内部,外部无法直接访问,实现了数据的封装和隐藏。

    参考文章:

    python小课堂26 – 进阶必修之闭包(一)

    https://zhuanlan.zhihu.com/p/55949749

    到此这篇关于python函数闭包概念的文章就介绍到这了,更多相关python函数闭包内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Python函数中闭包和延迟绑定详情
    • python 函数进阶之闭包函数
    • 详解python函数的闭包问题(内部函数与外部函数详述)
    • Python闭包函数定义与用法分析
    • python中的闭包函数
    • Python闭包之返回函数的函数用法示例
    • 实例讲解Python的函数闭包使用中应注意的问题
    • python中函数总结之装饰器闭包详解
    • Python函数中的函数(闭包)用法实例
    • Python中用函数作为返回值和实现闭包的教程

    站内搜索