【Python】闭包与装饰器

article/2025/8/27 20:28:34

1.闭包

闭包的本质就是函数的嵌套定义,即在函数内部再定义函数

闭包有两种不同的方式,第一种是“返回一个函数名称”,第二种是在函数内部就“直接调用”

闭包的定义:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用

引用是什么?Python 中的几乎所有东西都是对象,拥有属性和方法,包括整型,浮点型、函数,都是对象

返回一个函数名称:

# 定义外层函数
def outer():# 外函数临时变量num_01num1 = 100def inner():# 内函数里运用了外函数的临时变量num2 = num1 + 1print("num2 =",num2)# 外函数的返回值是内函数的引用return inner   outer()()  # print为:num2=101

outer外函数返回内函数 inner的引用

直接调用:

def outer():# 外函数临时变量num1num1 = 100def inner():# 内函数里运用了外函数的临时变量num2 = num1 + 1print("num2 =",num2)# 外函数的返回值是内函数的引用return inner()   outer()# print为:num2=101

闭包的优缺点 

优点

  • 可以避免使用全局变量,防止全局变量污染
  • 可以读取函数内部的变量
  • 延长了局部变量的作用域范围

缺点

  • 变量不会被收回,消耗内存
  • 会造成内存泄漏

 2.装饰器

采用了闭包的思路,在不改变原函数功能的情况下,为函数增添新的功能

装饰器的语法以@开头,接着是装饰器函数的名字和可选的参数。紧跟着装饰器声明的是被修饰的函数和装饰函数的可选参数

装饰器的应用场景:引入日志、函数执行时间统计、执行函数前预备处理、执行函数后清理功能、权限校验等场景、缓存、事务处理、数据清理、数据添加、附加功能等

格式:

# 外层函数
def outer(func):# 内层函数def inner():func()# 额外添加的功能print("hello")# 外层函数返回内层函数的引用return inner@outer   # 给gat函数添加 outer装饰器
def gat():passgat()# print为>> hello

装饰器作用:在不改变函数原有代码的基础上,添加额外的功能

参数传递 

1.装饰器形式

def outer(func):def inner():print("装饰器开始执行")print("功能添加")func()print("装饰器结束执行")return inner@outer   # 给add函数添加 outer装饰器
def add():print("hello")add()# print为>> 装饰器开始执行
#           功能添加
#           hello
#           装饰器结束执行

 2.装饰器传参形式

def outer(func):def inner(a, b):print("装饰器执行")print("A---B")func(a, b)print("装饰器结束执行")return inner@outer  # 给add函数添加一个outer装饰器
def add(a, b):print("a+b = ", (a+b))add(10,20)# print为>> 装饰器执行
#           A---B
#           a+b =  30
#           装饰器结束执行

3.不定长参数传参 

def outer(func):def inner(*args, **kwargs):print("装饰器执行")print("A---*---B")func(*args, **kwargs)print("装饰器结束执行")return inner@outer  # 给add函数添加一个outer装饰器
def add(a, b,c,d):print("a+b+c+d = ", (a+b+c+d))add(10, 20, 30, 40)# print为>> 装饰器执行
#           A---*---B
#           a+b+c+d =  100
#           装饰器结束执行

类装饰器

使用类来实现装饰器的功能的,称之为类装饰器 。类装饰器的实现是调用了类里面的__call__函数

类作为一个装饰器时: 

  1. 通过__init__()初始化类
  2. 通过__call__()调用真正的装饰方法
class ClsDecorator:def __init__(self, func):self.func = funcprint("执行类的__init__方法")def __call__(self, *args, **kwargs):print('__call__函数')self.func(*args, **kwargs)print("<call>函数")@ClsDecorator
def outer1():print("函数>>outer1")def outer():print("未使用类装饰器")@ClsDecorator
def outer2(name):print('函数》》outer2')name()print("倒数第二次执行")if __name__ == '__main__':outer1()outer2(outer)

打印结果:

多层装饰器 

def outer1(func):def inner(*args,**kwargs):print("装饰器1执行")print("A-----B")func(*args,**kwargs)print("装饰器1结束执行")return innerdef outer2(func):def inner(*args,**kwargs):print("装饰器2执行")print("C-----D")func(*args,**kwargs)print("装饰器2结束执行")return inner@outer1  # 给outers函数添加一个outer1装饰器
@outer2  # 给outers函数添加一个outer2装饰器
def outers(a, b,c,d):print("a+b+c+d = ", (a+b+c+d))outers(10, 20, 30, 40)# 运行结果 / 执行顺序
装饰器1执行
A-----B
装饰器2执行
C-----D
a+b+c+d = 100
装饰器2结束执行
装饰器1结束执行

多层装饰器开始执行时,自上而下开始执行装饰器功能,当执行完执行函数中的操作之后,自下而上的结束装饰器执行

常用内置装饰器

1.@staticmethod: 静态方法 ,没有和类本身有关的参数,无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用

2.@property:使调用类中的方法像引用类中的字段属性一样。被修饰的特性方法,内部可以实现处理逻辑,但对外提供统一的调用方式

3.@classmethod: 与staticmethod很相似,第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象

装饰器的优缺点

优点

  • 灵活性高,当需要扩展多个功能时,只需要增加新的具体装饰类即可
  • 装饰类和被装饰类可以独立发展,耦合性低,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能

缺点

  • 多层装饰较为复杂
  • 不能装饰@staticmethod 或者 @classmethod已经装饰过的方法
  • 装饰器会对原函数的元信息进行更改

http://chatgpt.dhexx.cn/article/PjnISMIt.shtml

相关文章

Python装饰器的通俗理解

看了这篇文章终于搞懂了装饰器&#xff0c;原文有少许错误&#xff0c;但无伤大雅&#xff0c;改正后转载于此&#xff0c;一起学习。 在学习Python的过程中&#xff0c;我相信有很多人和我一样&#xff0c;对Python的装饰器一直觉得很困惑&#xff0c;我也是困惑了好久&#x…

什么是装饰器?

一、引出装饰器概念 引入问题&#xff1a; 定义了一个函数&#xff0c;想在运行时动态的增加功能&#xff0c;又不想改动函数本身的代码&#xff1f; 示例&#xff1a; 希望对下列函数调用增加log功能&#xff0c;打印出函数调用&#xff1a; def f1(x): return x*2 d…

Python自定义装饰器

文章目录 1.闭包2.不带参数的装饰器3.带参数的装饰器4.不定长参数的装饰器5.多重装饰器修饰6.返回值是装饰器7.装饰器类 Python学习笔记—装饰器 装饰器&#xff1a;从生活角度理解&#xff0c;是对一个东西进行装饰&#xff0c;增加它本身的一些功能和内容&#xff1b; Python…

Python的装饰器

前言&#xff1a; &#x1f921; 作者简介&#xff1a;我是Morning&#xff0c;计算机的打工人&#xff0c;想要翻身做主人 &#x1f648; &#x1f648; &#x1f648; &#x1f3e0; 个人主页&#xff1a;Morning的主页 &#x1f4d5;系列专栏&#xff1a;&#…

装 饰 器

一&#xff0c;装饰器概念 装饰器本质上还是函数&#xff0c;让其它的函数在不做任何代码修改的情况下&#xff0c;增加额外的功能 所以说一句话&#xff1a;还是函数&#xff0c;记住奥 谈到一个原则&#xff1a;开发封闭原则 概念&#xff1a; 一个以函数作为参数并返回一…

学习TypeScript20(装饰器Decorator)

Decorator 装饰器是一项实验性特性&#xff0c;在未来的版本中可能会发生改变 它们不仅增加了代码的可读性&#xff0c;清晰地表达了意图&#xff0c;而且提供一种方便的手段&#xff0c;增加或修改类的功能 若要启用实验性的装饰器特性&#xff0c;你必须在命令行或tsconfig…

python装饰器详解

python中的装饰器(decorator)一般采用语法糖的形式&#xff0c;是一种语法格式。比如&#xff1a;classmethod&#xff0c;staticmethod&#xff0c;property&#xff0c;xxx.setter&#xff0c;wraps()&#xff0c;func_name等都是python中的装饰器。 装饰器&#xff0c;装饰的…

【Python】一文弄懂python装饰器(附源码例子)

目录 前言 一、什么是装饰器 二、为什么要用装饰器 三、简单的装饰器 四、装饰器的语法糖 五、装饰器传参 六、带参数的装饰器 七、类装饰器 八、带参数的类装饰器 九、装饰器的顺序 总结 写在后面 前言 最近有人问我装饰器是什么&#xff0c;我就跟他说&#xff…

偏微分方程数值解程序设计与实现——数学基础

常用算子符号 梯度算子 R d \mathbb{R}^d Rd空间中标量函数 u ( x ) u(\bf{x}) u(x)&#xff0c;其梯度算子定义如下&#xff1a; g r a d u ( x ) ∇ u ( x ) [ ∂ u ∂ x 0 ∂ u ∂ x 1 ⋮ ∂ u ∂ x d − 1 ] grad u(\mathbf{x})\nabla u(\mathbf{x}) \begin{bmatrix} …

偏微分方程的数值解(六): 偏微分方程的 pdetool 解法

偏微分方程的数值解系列博文&#xff1a; 偏微分方程的数值解(一):定解问题 & 差分解法 偏微分方程的数值解(二): 一维状态空间的偏微分方程的 MATLAB 解法 偏微分方程的数值解(三): 化工应用实例 ----------触煤反应装置内温度及转换率的分布 偏微分方程的数值解(四):…

微分方程数值解

一阶问题举例&#xff1a; 高阶问题举例 &#xff1a; 常微分方程数值解&#xff1a;向前欧拉方法之一阶问题 clc,clear,close all; a0;%初始时刻 b2*pi;%结束时刻 n100;%离散点数量 x00;%初值 h(b-a)/n;%步长 xx0 [0:n]*h;%离散点数组 funinline(sin(x)y,x,y); y01; %计算 y(…

常微分方程数值解法1

&#xff11;.牛顿迭代法 多数方程不存在求根公式&#xff0c;因此求精确根非常困难&#xff0c;甚至不可能&#xff0c;从而寻找方程的近似根就显得特别重要。牛顿迭代法使用函数 的泰勒级数的前面几项来寻找方程 的根。牛顿迭代法是求方程根的重要方法之一&#xff0c;其最大…

差分、偏微分方程的解法

这里写目录标题 微分方程数值求解——有限差分法matlab代码差分法的运用&#xff08;依旧是连续变量——>离散网格点&#xff09; PDE求解思路demo1demo2 微分方程数值求解——有限差分法 差分方法又称为有限差分方法或网格法&#xff0c;是求偏微分方程定解问题的数值解中…

微分方程数值解法(2)——椭圆型方程的有限差分法

此处参考教材为李荣华的《微分方程数值解法》 使用工具&#xff1a;Matlab 1. 算法&#xff1a;矩形网格上5点差分格式 2. 算法 I.需要求解的函数 function [v,vx,vy,f,aa,bb,cc,dd]u2D(x,y,ft)% ft为方程编号&#xff0c;u1D为精确解函数u&#xff08;t&#xff09;,注意与…

基础数学(8)——常微分方程数值解法

文章目录 期末考核方式基础知识解析解&#xff08;公式法&#xff09;解析解例题&#xff08;使用公式法&#xff0c;必考&#xff09;解析解的局限性 数值解数值解的基本流程 显示Euler法显示欧拉&#xff08;差值理解&#xff09;显示欧拉&#xff08;Taylor展开理解&#xf…

微分方程数值解法(1)——常微分方程初值问题的数值解法

此处参考教材为李荣华的《微分方程数值解法》 使用工具&#xff1a;Matlab 1. 算法 注: 最后一行应为k4,上面为笔误 2. 算法 I.需要求解的函数 function ff1D(t,u,ft)% ft为方程编号&#xff0c;u1D为精确解函数u(t),注意与f1D对应右端项函数f(t,u(t))switch ftcase 1 %P10…

偏微分方程数值解法pdf_天生一对,硬核微分方程与深度学习的联姻之路

机器之心原创 作者&#xff1a;蒋思源 微分方程真的能结合深度神经网络&#xff1f;真的能用来理解深度神经网络、推导神经网络架构、构建深度生成模型&#xff1f;本文将从鄂维南、董彬和陈天琦等研究者的工作中&#xff0c;窥探微分方程与深度学习联袂前行的路径。 近日&…

椭圆型偏微分方程数值解法

一、 一维椭圆方程数值解 matlab代码&#xff1a; function chap2_fdm_elliptic_1D % 一维椭圆方程求解(常微分方程边值问题) % -u q(x)u f(x), 0<x<1, 取q(x) x, f(x) (x-1)exp(x) % u(0) 1, u(1) e; 边界条件 % 真解为 u exp(x)N 20; h 1/N; x_al…

Python小白的数学建模课-11.偏微分方程数值解法

偏微分方程可以描述各种自然和工程现象&#xff0c; 是构建科学、工程学和其他领域的数学模型主要手段。 偏微分方程主要有三类&#xff1a;椭圆方程&#xff0c;抛物方程和双曲方程。 本文采用有限差分法求解偏微分方程&#xff0c;通过案例讲解一维平流方程、一维热传导方程…

偏微分方程数值解法pdf_单摆-微分方程浅谈

引子[1] 单摆&#xff0c;这个在中学物理都学过的东西&#xff0c;应该是非常熟悉了。 图片来源-维基百科 小角度简单摆 若最高处( )的绳子和最低处(速度最大值)的绳子的角度为 &#xff0c;则可使用下列公式算出它的振动周期。 公式证明 摆球受力分析 绳与对称线夹角为 &…