当前位置: 首页 > news >正文

[Python]闭包

在这里插入图片描述


前言

系列文章目录
[Python]目录
视频及资料和课件
链接:https://pan.baidu.com/s/1LCv_qyWslwB-MYw56fjbDg?pwd=1234
提取码:1234


文章目录

  • 前言
  • 1. 闭包的介绍
    • 1.1 闭包的定义
    • 1.2 闭包的构成条件
    • 1.3 闭包的作用
  • 2. 简单闭包的示例代码
  • 3. 闭包的使用
    • 3.1 需要进行实现的案例
    • 3.2 实现步骤说明
    • 3.3 代码实现
  • 4. 修改闭包内使用的外部变量
    • 4.1 错误示例
    • 4.2 正确示例


1. 闭包的介绍

我们前面已经学过了函数,我们知道当函数调用完,函数内定义的变量都销毁了,但是我们有时候需要保存函数内的这个变量,每次在这个变量的基础上完成一些列的操作,比如: 每次在这个变量的基础上和其它数字进行求和计算。

我们就可以通过闭包来解决这个需求。

1.1 闭包的定义

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

1.2 闭包的构成条件

通过闭包的定义,我们可以得知闭包的形成条件:
(1)在函数嵌套(函数里面再定义函数)的前提下
(2)内部函数使用了外部函数的变量(还包括外部函数的参数)
(3)外部函数返回了内部函数

1.3 闭包的作用

闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。

2. 简单闭包的示例代码

# 定义一个外部函数
def func_out(num1):
    # 定义一个内部函数
    def func_inner(num2):
        # 内部函数使用了外部函数的变量(num1)
        # 内部函数必须使用外部函数的变量
        result = num1 + num2
        print("结果是:", result)
    # 外部函数返回了内部函数,这里返回的内部函数就是闭包
    return func_inner

# 获取闭包对象
# f 就是闭包  
# 这里 f = func_inner
f = func_out(1)
# 执行闭包
f(2)
f(3)

在这里插入图片描述

闭包执行结果的说明:
通过上面的输出结果可以看出闭包保存了外部函数内的变量num1,每次执行闭包都是在num1 = 1 基础上进行计算。

注意点:
由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。闭包不释放,外部函数内的变量被闭包一直持有,外部函数内的变量不能释放,只有当闭包释放,与闭包有关的才能进行释放。

3. 闭包的使用

3.1 需要进行实现的案例

需求:
根据配置信息使用闭包实现不同人的对话信息,例如对话:
张三: 到北京了吗?
李四: 已经到了,放心吧。

3.2 实现步骤说明

  1. 定义外部函数接收不同的配置信息参数,参数是人名,即人名使用外部函数进行保存。
  2. 定义内部函数接收对话信息参数,内部函数使用外部函数的人名变量,进行对话的实现。
  3. 在内部函数里面把配置信息和对话信息进行拼接输出。

3.3 代码实现

# 外部函数保存人名信息,外部函数接收姓名为参数
def config_name(name):
    # 内部函数实现对话,内部函数使用外部函数保存的姓名,完成对话
    def inner(msg):
        print(name + ':' + msg)

    # 获取内部函数的内存地址,查看创建的闭包是否会相同
    print(id(inner))
    # 外部函数返回内部函数
    return inner


# 创建tom闭包实例
tom = config_name('tom')
# 创建jerry闭包实例
jerry = config_name('jerry')

# 执行闭包
tom('到北京了吗?')
jerry('已经到了,放心吧。')

在这里插入图片描述

4. 修改闭包内使用的外部变量

4.1 错误示例

# 外部函数
def f_out():
    # 外部函数的变量
    num = 10

    # 内部函数
    def f_inner():
        # 修改外部函数变量的值
        num = 11
        # 内部函数使用外部函数的变量
        res = num + 10
        print(res)

    # 验证是否可以修改外部变量
    print('修改前的num值:', num)
    # 调用内部函数修改外部函数的变量
    f_inner()
    print('修改前的num值:', num)

    # 返回内部函数
    return f_inner


# 创建闭包
f = f_out()
f()

在这里插入图片描述

没有成功修改外部变量的值,是由于在内部函数num=11相当于创建了一个局部变量num与外部函数的num不同,所以不能修改外部函数的变量值。

4.2 正确示例

修改闭包内使用的外部变量,需要使用关键字:nonlocal,告诉解释器,此处使用的是 外部变量

# 外部函数
def f_out():
    # 外部函数的变量
    num = 10

    # 内部函数
    def f_inner():
        # 修改外部函数变量的值
        # nonlocal 使用此关键字告诉解释器,这里使用的是外部函数的变量 num
        nonlocal num
        # 修改外部变量的值
        num = 11
        # 内部函数使用外部函数的变量
        res = num + 10
        print(res)

    # 验证是否可以修改外部变量
    print('修改前的num值:', num)
    # 调用内部函数修改外部函数的变量
    f_inner()
    print('修改前的num值:', num)

    # 返回内部函数
    return f_inner


# 创建闭包
f = f_out()
f()

在这里插入图片描述

相关文章:

  • 《C++程序设计原理与实践》笔记 第5章 错误
  • 静息态fMRI方法在脑动力学表征上的比较
  • LabVIEW自动整理程序框图
  • 拨测API接口+监控方案
  • 第一性原理详解
  • 信息化转型?数字化转型?企业到底该如何选择
  • ES6的Class继承--super关键字
  • Linux 简单命令 - find -grep命令深入学习
  • OP-TEE driver(五):libteec库中的接口在驱动中的实现
  • F-003 FPGA基础配置
  • java-php-python-ssm百分百教育集团教务管理系统设计计算机毕业设计
  • Apple M1 Macos 安装虚拟机软件UTM
  • 167.两数之和II-输入有序数组 || 双指针
  • aspnetcore6.0源代码编译调试
  • 【力扣刷题】Day04——链表专题
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • ES6语法详解(一)
  • javascript数组去重/查找/插入/删除
  • JS基础之数据类型、对象、原型、原型链、继承
  • Leetcode 27 Remove Element
  • Linux CTF 逆向入门
  • python_bomb----数据类型总结
  • Windows Containers 大冒险: 容器网络
  • 创建一个Struts2项目maven 方式
  • 京东美团研发面经
  • 理解在java “”i=i++;”所发生的事情
  • 理清楚Vue的结构
  • 码农张的Bug人生 - 见面之礼
  • 区块链分支循环
  • 思否第一天
  • 原生 js 实现移动端 Touch 滑动反弹
  • 在Unity中实现一个简单的消息管理器
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​2021半年盘点,不想你错过的重磅新书
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #include<初见C语言之指针(5)>
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (安卓)跳转应用市场APP详情页的方式
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)ssm高校实验室 毕业设计 800008
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (十五)使用Nexus创建Maven私服
  • (十一)手动添加用户和文件的特殊权限
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)Linq学习笔记
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .NET CLR Hosting 简介
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .net经典笔试题