Python的装饰器

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

前言:
    🤡 作者简介:我是Morning,计算机的打工人,想要翻身做主人 🙈 🙈 🙈
    🏠 个人主页:Morning的主页
    📕系列专栏::Morning的Python专栏
    📞 如果小编的内容有欠缺或者有改进,请指正拙著。期待与大家的交流
    🔥如果感觉博主的文章还不错的话,👍点赞👍 + 👀关注👀 + 🤏收藏🤏

目录

一.闭包

1.闭包的必要性

2.定义

3.调用和引用的区别

二.装饰器

1.定义:

2.意义

3.实现方式

4.使用案例

(1)原来思维

(2)使用闭包实现装饰器

三.语法糖

1.简介

2.使用案例

(1)简单的直接使用

(2)有传参

(3)使用函数嵌套进行语法糖传参

3.类与装饰器的使用

(1)装饰类方法

(2)装饰类


一.闭包

在今后的学习中装饰器会起到很大的作用,而装饰器就是基于闭包来实现的

1.闭包的必要性

在一个函数中如果想要想要使用一个变量,我们最直接的方法就是设置一个全局变量。但是这个变量如果只会使用一两次,那么直到代码进行结束前,那个全局变量一直都会占用着资源,不会被销毁,会浪费资源。

2.定义

一个函数中若要用到另一个函数的参数,则可以通过闭包的形式来实行

顾名思义,闭包(封闭包含),在下面这段函数中便能体现出来

def A():a=1def B():b=2print(a)

对于函数闭包而言,某一个函数中用到的变量的作用域,取决于其上层或者本层函数函数的作用域。

对于嵌套函数而言,内层函数中定义的变量是无法在外层函数进行使用的(即在B函数中可以调用a,但是不能在A函数中调用b)

此外可以直接调用函数A(),但是不能调用函数B()

3.调用和引用的区别

调用:会直接从内存中去取出相应的对象执行,代码会直接执行

引用:设置了一个路标,该路标指向某一个内存地址中的对象。此时相当于加载了代码在一个缓存空间内,代码并没有被执行。

提醒:如果在没有返回值return的情况下调用闭包函数时,只会调用外层函数,不会调用内层函数

def Student():name="susu"age=21print(f"{name}{age}了")def School():adress="河北"banji=204print(name+"在"+adress+"上学")return School
s=Student()
print(s)   #结果见图一
def Student():name="susu"age=21print(f"{name}{age}了")def School():adress="河北"banji=204print(name+"在"+adress+"上学")return School
Student()
School()  #结果见图二
def Student():name="susu"age=21print(f"{name}{age}了")def School():adress="河北"banji=204print(name+"在"+adress+"上学")return School
Student()() #结果见图三
​
def Student():name="susu"age=21print(f"{name}{age}了")def School():adress="河北"banji=204print(name+"在"+adress+"上学")return School()
Student()  #结果见图四
​

图一

 

图二

图三

 

图四:

在上面的例子中,School便是引用,School()则是调用。在return School的情况下调用Student函数会发现运行结果中出现的是School函数(即图一);如果调用Student函数的基础上再加个()那么School函数也会被调用(即图三)。

二.装饰器

1.定义:

能够在不改变原有函数的基础上,在原来的基础上添加额外的功能的代码,就叫做装饰器

2.意义

登陆注册(验证账号、密码的准确性)、爬虫中(某一个请求需要在异常之后补充请求头参数然后再去重新对当前请求进行发送)

3.实现方式

对于装饰器的定义,基于函数闭包的形式来实现,即可以将某一个函数作为参数传递给另一个函数,在这另一个函数中去为函数添加功能。

4.使用案例

(1)原来思维

def index():print("这里有着大家要的学习资料")print("suyuxi")
#对于index而言,它的功能是已经实现了的,不希望重构代码
#(编程都流传着一句话,只要你的程序跑起来,哪怕你知道它有bug那也不要去改哈哈哈)所以登陆的权限就交给了其他的函数来实现
def login(func,username,password):if username=="sumaolin" and password=="aisuyuxi":func()#传递实参来调用函数else:print("你无权限,请与管理员联系")return 0
login(index,"sumaolin","aisuyuxi")

但是这样的代码可读性并不高。一个函数就添加了三个参数,阅读起来就需要一点一点地去理解,不用说肯定很烦。

(2)使用闭包实现装饰器

那我们有没有一种方法来直接调用index函数呢?那我们就要使用闭包函数来实现装饰器

def index():print("这里有着大家要的学习资料")print("suyuxi")
#下面便是一个自定义的装饰器。用inner函数来进行修饰func,如果满足条件后再来调用func。从而实现为func添加功能
def login(func):username="sumaolin"password="aisuyuxi"def inner():if username == "sumaolin" and password == "aisuyuxi":return func()else:print("你无权限,请与管理员联系")return 0return inner
login(index)()

此处可能会有人问,为什么不直接返回inner(),而是返回inner。其实两个都能达到我们的目的,只是在此例中我更想突出的是:inner是为了给func添加功能,因此返回的是func函数,然后在对其进行调用

但是说到底我们还是阅读起来不直观,还是需要一步一步地去理解。我们想要一个阅读性更强的代码,那么语法糖就可以解决这个问题

三.语法糖

1.简介

python中去执行修饰器的一种语法规则

写法:@decorator 语法糖都要写在某一个函数定义的头上,表示decorator函数修饰下面的函数

那为什么要去使用它呢。简单理解的话,就是如果你要去修饰一栋墙,你肯定不会是去把墙拆了重新修,而是在之前的基础上进行修饰。代码也是如此,原先的代码我们能不动的话就不动,然后写修饰代码来对原代码进行修饰。

2.使用案例

(1)简单的直接使用

def login(func):   #接收被修饰的对象(对象可以是函数、类、类中的方法)username="sumaolin"password="aisuyuxi"def inner():if username == "sumaolin" and password == "aisuyuxi":return func()else:print("你无权限,请与管理员联系")return 0return inner
#语法糖出现在函数上方,此处表示index函数被装饰器login装饰,login叫做装饰器(n.也叫装饰函数)
#login修饰index的过程是叫装饰函数(v.)
@login
def index():print("这里有着大家要的学习资料")print("suyuxi")
index()

大家可以看出来除了语法糖的使用外只有调用不同,曾经我都怀疑过是否生效了。

大家仔细看我的注释的话是可以理解的,在外层接受了被装饰的对象index(也可以理解为func是被装饰的对象,即index。所以func就是index)

这样已经可以实现一个比较简单的语法糖了。

(2)有传参

def login(func):   #最外层接收被修饰的对象(对象可以是函数、类、类中的方法)username="sumaolin"password="aisuyuxi"def inner(level):#2if username == "sumaolin" and password == "aisuyuxi":return func(level)#3else:print("你无权限,请与管理员联系")return 0return inner
#语法糖出现在函数上方,此处表示index函数被装饰器login装饰,login叫做装饰器(n.也叫装饰函数)
#login修饰index的过程是叫装饰函数(v.)
@login
def index(level):#4print("这里有着大家要的学习资料")print("suyuxi")
index(1)#1

在注释中我标注了四个数字。如果我们想要在4处,即我们想要实现的主要代码添加一个形参。那么我们就需要在1处添加实参。但是在调用时3处func的调用肯定也是需要一个形参的,此时的inner又必须与func保持一致,所以2处也必须添加形参。

总的来说,添加一个实参,就需要添加三个形参,说到底我们还是将问题复杂了。

(3)使用函数嵌套进行语法糖传参

但是在进行传参时我们需要注意是不能在装饰器函数设置形参的。最好的方法就是再进行函数的嵌套

def sugar(level):def login(func):username="sumaolin"password="aisuyuxi"def inner():if username == "sumaolin" and password == "aisuyuxi":print(f"您的会员等级为{level}")return func()else:print("你无权限,请与管理员联系")return 0return innerreturn login
@sugar(3)
def index():print("这里有着大家要的学习资料")print("suyuxi")
index()

3.类与装饰器的使用

(1)装饰类方法

def decorator(func):#print(func)def inner():#1return func()#2return inner
​
class A:@decoratordef hobby(self):print("打苏钰烯")
a=A()
a.hobby()

按照我们以前的思想,应该是这么写,但是运行后报错。为了便于理解我们打印一下func到底是什么

我们可以看出是类A的实例方法hobby,那么在1和2处我们就需要接受一个self

def decorator(func):print(func)def inner(self):#1return func(self)#2return inner
​
class A:@decoratordef hobby(self):print("打苏钰烯")
a=A()
a.hobby()

(2)装饰类

def decorator(func):def inner():return func()return inner
@decorator  #该装饰器装饰的是整个类,而不是一个单独的方法,在对类实例化的时候就会调用装饰器
class A:def hobby(self):print("kkk")def love(self):print("girl")
a=A()
a.hobby()
a.love()

修饰类的话,那么类中的方法对会被修饰

以上便是我对装饰器的理解,感觉还是不到位,讲解的也十分抽象,因为在实际中的使用还很少。但是会加油的,期待与大家的交流。

还有一位博主的语法糖讲解的比我说的更加条例高效,大家可以看一看(5条消息) Python语法糖装饰器---由浅入深(看一遍就懂系列)_Felix-微信(Felixzfb)的博客-CSDN博客


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

相关文章

装 饰 器

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

学习TypeScript20(装饰器Decorator)

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

python装饰器详解

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

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

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

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

常用算子符号 梯度算子 R d \mathbb{R}^d Rd空间中标量函数 u ( x ) u(\bf{x}) u(x),其梯度算子定义如下: 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 解法

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

微分方程数值解

一阶问题举例: 高阶问题举例 : 常微分方程数值解:向前欧拉方法之一阶问题 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

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

差分、偏微分方程的解法

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

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

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

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

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

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

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

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

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

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

一、 一维椭圆方程数值解 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;则可使用下列公式算出它的振动周期。 公式证明 摆球受力分析 绳与对称线夹角为 &…

偏微分方程数值解法pdf_数值模拟偏微分方程的三种方法:FDM、FEM及FVM

偏微分方程数值模拟常用的方法主要有三种:有限差分方法(FDM)、有限元方法(FEM)、有限体积方法(FVM),本文将对这三种方法进行简单的介绍和比较。 一.有限差分方法 有限差分方法(Finite Difference Methods)是数值模拟偏微分方程最早采用的方法,至今仍被广泛运用。该方法包括区…

正圆锥体空间方程_数值模拟偏微分方程的三种方法:FDM、FEM及FVM

偏微分方程数值模拟常用的方法主要有三种:有限差分方法(FDM)、有限元方法(FEM)、有限体积方法(FVM),本文将对这三种方法进行简单的介绍和比较。 一.有限差分方法 有限差分方法(Finite Difference Methods)是数值模拟偏微分方程最早采用的方法,至今仍被广泛运用。该方法包括区…

抖音图标

抖音图标&#xff1a; 1.创建一张画布&#xff0c;再用圆角矩形工具创建一个圆角矩形 2.新建一个图层&#xff0c;用椭圆选框工具创建一个圆&#xff0c;再alt键从选区减去一个圆 3.再填充一个颜色&#xff0c;再剪切1/4圆接着粘贴拖拽至右上方 4.新建一个图层&#xff0c;用…

抖音图标——ps

抖音图标 1.用圆角矩形工具画个圆角&#xff08;空格键可以移动&#xff09;&#xff0c;填充为黑色&#xff0c;把此图层转换为珊格式化 2.再新建一个图层&#xff0c;用椭圆选框工具画个换个环&#xff08;用alt会出现&#xff0c;shift会出现加号&#xff09; 3.Ctrlx剪…