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

‘闭包‘, ‘装饰器‘及其应用场景

‘闭包’, '装饰器’及其应用场景

一, 闭包及其应用场景

图解

在这里插入图片描述

闭包的定义

概述: 内部函数 使用了 外部函数 的变量, 这种写法就称之为闭包.
格式:

def 外部函数名(形参列表):
	外部函数的(局部)变量
	def 内部函数名(形参列表):
		内部函数的(局部)变量

	return 内部函数名

前提条件:

  1. 有嵌套. 外部函数嵌套内部函数
  2. 有引用. 内部函数引用外部函数的变量
  3. 有返回. 外部函数中, 返回 内部函数名(对象)

细节:
函数名函数名() 是两个概念, 前者表示 函数对象 , 后者表示 调用函数, 获取返回值 .

案例

案例(1): 观察函数名函数名()
案例需求

创建函数, 分别打印函数名函数名()
证明: 函数名 -> 是对象, 函数名() -> 是调用函数, 获取返回值

实现思路
  1. 创建函数.
  2. 打印函数名.
  3. 打印函数名().
  4. 将函数名赋值给变量, 这个变量就是: 函数对象.
  5. 打印函数对象.
  6. 打印函数对象().
# 1. 创建函数.
def get_sum(a, b):
	return a + b
# 2. 打印函数名.
print(get_sum)	# <function get_sum at 0x000001B4AC3DD800>, 对象.
# 3. 打印函数名().
print(get_sum(10, 20))		# 调用函数, 获取返回值.

# 4. 将函数名赋值给变量, 这个变量就是: 函数对象.
my_sum = get_sum
# 5. 打印函数对象.
print(my_sum)	# <function get_sum at 0x00000251CE53D800>
print(my_sum(100, 200))	# 300
案例(2): 闭包写法
案例需求

定义求和的闭包, 外部函数有参数num1, 内部函数有参数num2, 调用, 求解两数之和, 观察结果.

实现思路
  1. 定义外部函数.
  2. 定义内部函数.
  3. 求和.
  4. 调用上述函数.
  5. 另一种调用方式.
# 1. 定义外部函数.
def fn_outer(num1):
	# 2. 定义内部函数.
	def fn_inner(num2):					# 有嵌套
		# 3. 求和
		sum = num1 + num2				# 有引用
		print(f'求和结果: {sum}')
	return fn_inner						# 有返回

# 4. 调用上述的函数.
fn_inner = fn_outer(10)
fn_inner(20)
# 5. 另一种调用方式.
fn_inner(100)(200)

二, nonlocal关键字介绍

nonlocal关键字的定义

nonlocal关键字是Python内置的关键字, 可以实现 在内部函数中 修改外部函数的 变量值.

图解

在这里插入图片描述

案例需求

编写1个闭包, 让内部函数访问外部函数的参数 a = 100, 并观察结果.

实现思路

  1. 定义外部函数.
  2. 定义外部函数的(局部)变量.
  3. 定义内部函数, 访问外部函数的变量.
  4. 在内部函数中修改外部函数的变量.
  5. nonlocal: 可以实现在内部函数修改外部函数的变量值.
  6. 打印外部函数的变量.
  7. 返回 内部函数名(对象).
# 1. 定义外部函数.
def fn_outer()
	# 2. 定义外部函数的(局部)变量.
	a = 100
	# 3. 定义内部函数, 访问外部函数的变量.
	def fn_inner()
		# 4. 在内部函数中修改外部函数的变量.
		# 5. nonlocal: 可以实现在内部函数中修改外部函数的变量值.
		nonlocal a
		a = a + 1
		# 6. 打印外部函数的变量.
		print(f'a: {a}')

	# 7. 返回 内部函数名(对象)
	return fn_inner

# 8. 调用函数
fn_inner = fn_outer()
fn_inner()	# 101
fn_inner()	# 102
fn_inner()	# 103
		

三, 装饰器及其应用场景

装饰器的定义

概述:

装饰器的本质是1个闭包函数, 目的是 在不改变原有函数的基础上, 对1其功能做增强.
大白话: 装修队 在不改变房屋结构的情况下, 对房屋做装饰(功能增强).

提前条件:
  1. 有嵌套.
  2. 有引用.
  3. 有返回.
  4. 有额外功能.
格式:
  • 方法一: 传统写法.
修饰后的函数名 = 装饰器名(被装饰的原函数名)
装饰后的函数名()
  • 方法二: 语法糖.
在要被装饰的原函数上, 直接写 @装饰器名, 之后直接调用原函数即可.
图解:在这里插入图片描述

案例

案例(1): 发表评论.
案例需求

在发表评论前, 都是需要先登录的.

实现思路
  1. 定义外部函数, 形参列表接收 要被装饰的函数名(对象)
  2. 定义内部函数.
  3. 额外功能.
  4. 访问原函数, 即: 外部函数的引用.
  5. 返回内部函数对象.
  6. 定义函数, 表示 发表评论.
  7. 定义函数, 表示 充值中…
  8. 传统方式.
  9. 语法糖方式.
# 1.定义外部函数, 形参列表接收 要被装饰的函数名(对象)
def check_login(fn_name):       # fn_name: 被装饰的函数名(对象)
    # 2. 定义内部函数.
    def fn_inner():             # 有嵌套
        # 3. 额外功能
        print('校验登陆... 登陆成功!')
        # 4. 访问原函数, 即: 外部函数的引用.
        fn_name()               # 有引用
    # 5.  返回内部函数对象.
    return fn_inner             # 有返回

# 6. 定义函数, 表示 发表评论.
def comment():
    print("发表评论")
# 7. 定义函数, 表示 充值中....
@check_login    # 底层其实是: payment = check_login(payment)
def payment():
    print('充值中...')

# 8. 传统方式.
comment = check_login(comment)
comment()
# 9. 语法糖方式.
# payment = check_login(payment)
# payment()
payment()

案例(2): 装饰器装饰_无参无返回的原函数
细节

装饰器的内部函数格式 要和 被装饰的原函数 保持一致.
即:原函数是无参无返回的, 则 装饰器的内部函数也必须是 无参无返回的.
原函数有参有返回的, 则 装饰器的内部函数也必须是 有参有返回的.

案例需求

装饰器装饰_无参无返回的原函数

实现思路
# 需求: 定义无参无返回值的 get_sum()求和函数, 在不改变其代码的基础上, 添加友好提示: 正在努力计算中...
# 1. 定义装饰器.
def my_decorator(fn_name):
    # 2. 定义内部函数, 其格式必须和 被装饰的原函数 保持一致.
    def fn_inner():                 # 有嵌套
        # 3. 添加提示信息(额外功能)
        print('正在努力计算中...')     # 有额外功能
        # 4. 调用原函数.
        fn_name()                   # 有引用
    # 5. 返回内部函数(对象)
    return fn_inner                 # 有返回


# 6. 定义原函数.
@my_decorator		# @装饰器名
def get_sum():
    a = 10
    b = 20
    sum = a + b
    print(f'sum求和结果: {sum}')


# 7. 传统方式.
# get_sum = my_decorator(get_sum)
# get_sum()

# 8. 语法糖方式.
get_sum()
案例(3): 装饰器装饰_有参无返回值的原函数
细节

装饰器的内部函数格式 要和 被装饰的原函数 保持一致.
即:原函数是无参无返回的, 则 装饰器的内部函数也必须是 无参无返回的.
原函数有参有返回的, 则 装饰器的内部函数也必须是 有参有返回的.

案例需求

装饰器装饰_有参无返回值的原函数

实现思路
# 需求: 定义有参无返回值的 get_sum()求和函数, 在不改变其代码的基础上, 添加友好提示: 正在努力计算中...
# 1. 定义装饰器.
def my_decorator(fn_name):
    # 2. 定义内部函数
    def fn_inner(x, y):
        # 3. 额外功能
        print('正在努力计算中...')
        # 4. 调用原函数.
        fn_name(x, y)
    # 5. 返回内部函数.
    return fn_inner

# 6. 定义原函数, 有参无返回值.
@my_decorator
def get_sum(a, b):
    sum = a + b
    print(f'sum求和结果: {sum}')


# 7. 传统方式.
# get_sum = my_decorator(get_sum)
# get_sum(10, 20)

# 8. 语法糖方式.
get_sum(10, 20)

四, 总结

  • Q1:闭包的定义
    • 概述: 内部函数 使用了 外部函数 的变量, 这种写法就称之为闭包.
    • 格式:

相关文章:

  • 西门子200smart之modbus_TCP(做从站与第三方设备)通讯
  • 从头开始学C语言第二十九天——指针数组
  • JavaScript-日期对象与节点操作详解
  • Apache Flink技术原理深入解析:任务执行流程全景图
  • Rocky9.2 编译安装Intel WIFI系列无线网卡驱动
  • 华为终端将全面进入鸿蒙时代
  • LLM - CentOS上离线部署Ollama+Qwen2.5-coder模型完全指南
  • Mimalloc论文解析:小内存管理的极致追求与实践启示
  • 虚拟机访问主机的plc仿真
  • C++学习之网盘项目单例模式
  • Swift 经典链表面试题:如何在不访问头节点的情况下删除指定节点?
  • FPGA 以太网通信(四)网络视频传输系统
  • c#难点整理2
  • windows下利用Ollama + AnythingLLM + DeepSeek 本地部署私有智能问答知识库
  • CVPR 2025 | 文本和图像引导的高保真3D数字人高效生成GaussianIP
  • 美国国家数据浮标中心(NDBC)
  • Leetcode刷题笔记1 图论part03
  • LangChain Chat Model学习笔记
  • 【Docker系列一】Docker 简介
  • 1、正点原子ZYNQ最小系统--GPIO之MIO控制LED笔记
  • 潘功胜在美谈关税:吁全球经济勿滑向“高摩擦、低信任”轨道
  • 沂水县委书记陈士贤,跨市履新泰安市委常委、组织部部长
  • 文旅部:今年一季度国内出游人次17.94亿,同比增长26.4%
  • 视频·世界读书日|王弘治:信息轰炸也会让文化体力透支
  • 深一度|坚守17年,这件事姚明就算赔钱也在继续做
  • 安徽一季度GDP为12265亿元,同比增长6.2%