装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为"装饰器"(Decorator),装饰器的功能非常强大,装饰器一般接受一个函数对象作为参数,以对其进行增强,相当于C++中的构造函数,与析构函数。

装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有迫切需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用.

  • 装饰器本身也是一个函数,其作用是,用于装饰其他函数.
  • 装饰器是一个闭包函数是嵌套函数,通过外层函数提供嵌套函数的环境
  • 装饰器在权限控制,增加额外功能,如增加记录日志,缓存处理,发送邮件用的比较多

6.1 无参装饰器

原函数中不带参数的装饰器,如下例子假设:我定义了一个函数lyshark(),现在想要在不改变原来函数定义的情况下,在函数运行前打印一段话,函数运行后打印另一段话,此时我们可以使用装饰器的装饰功能来简单的实现这个需求.

>>> import os
>>> import sys
>>>
>>> def outer(function):
def inner():
print("主函数开始执行前,会先执行我!")
result=function()
print("主函数执行结束后,要在执行我!")
return result
return inner # (1) @ + 函数名,直接作用在需要装饰的函数上一行
# (2) 自动执行outer函数并且将下面的函数名lyshark()当做参数传递到outer()
# (3) 将outer函数的返回值inner,重新赋值给lyshark()函数
>>> @outer
def lyshark():
print("lyshark 的主函数体,装饰器在装饰我(*^_^*)")
return "check ok" #==调用并执行函数,结果如下==========================================
>>> ret=lyshark()
主函数开始执行前,会先执行我!
lyshark 的主函数体,装饰器在装饰我(*^_^*)
主函数执行结束后,要在执行我! >>> print("lyshark()函数的返回值: ",ret)
lyshark()函数的返回值: check

上方代码的执行流程是这样的,步骤如下:

  • 1.当我们调用lyshark()函数时,会自动检查lyshark()函数上是否有装饰器
  • 2.如果有则将lyshark()函数的指针,传递给装饰器outer(function)
  • 3.outer(function)接到指针后,执行嵌套函数内的inner(),则先执行print打印一段话
  • 4.由于lyshark()函数指针,传递给了function变量,执行function()则相当于执行lyshark()
  • 5.接着最后一步执行打印一段结束的话,并执行返回,返回inner

6.2 有参装饰器

原函数带一个参数的装饰器: 我们在以上的案例中,给装饰器添加一个参数,并在内部使用这个参数.

>>> import os
>>> import sys
>>>
>>> def outer(function):
def inner(args):
print("主函数开始执行前,会先执行我!")
ret=function(args)
print("主函数执行结束后,要在执行我!")
return ret
return inner >>> @outer
def lyshark(args):
print(args)
return 0 #==调用并执行函数,结果如下==========================================
>>> ret=lyshark("hello world!")
主函数开始执行前,会先执行我!
hello world!
主函数执行结束后,要在执行我! >>> print("lyshark 的返回值是:",ret)
lyshark() 函数的返回值是: 0

原函数带两个参数的装饰器: 接下来继续演示一下,带有两个参数的装饰器,3个4个,以此类推.

>>> import os
>>> import sys
>>>
>>>
>>> def outer(function):
def inner(x,y):
print("主函数开始执行前,会先执行我!")
ret=function(x,y)
print("主函数执行结束后,要在执行我!")
return ret
return inner >>> @outer
def lyshark(x,y):
print(x,y)
return 0 #==调用并执行函数,结果如下==========================================
>>> ret=lyshark("Hello","LyShark")
主函数开始执行前,会先执行我!
Hello LyShark
主函数执行结束后,要在执行我! >>> print("lyshark() 函数的返回值是:",ret)
lyshark() 函数的返回值是: 0

传递一个万能参数: 装饰器也可传递一个万能参数,通过此参数传递列表字典等.

>>> import os
>>> import sys
>>>
>>> def outer(function):
def inner(*args,**kwargs):
print("主函数开始执行前,会先执行我!")
ret=function(*args,**kwargs)
print("主函数执行结束后,要在执行我!")
return ret
return inner >>> @outer
def lyshark(*args):
print(args)
return 0 #==调用并执行函数,结果如下==========================================
>>> num=[1,2,3,4,5]
>>> ret=lyshark(num)
主函数开始执行前,会先执行我!
([1, 2, 3, 4, 5],)
主函数执行结束后,要在执行我!
>>>
>>> print("lyshark() 函数的返回值是:",ret)
lyshark() 函数的返回值是: 0 #==调用并执行函数,结果如下==========================================
@outer
def lyshark_kw(*args,**kwargs):
print(args,kwargs)
return 0 num=[1,2,3,4,5]
kw={"1001":"admin","1002":"guest"}
ret=lyshark_kw(num,kw)

一次使用两个装饰器装饰函数: 如果一个装饰器不够用的话,我们可以使用两个装饰器,首先将函数与内层装饰器结合然后在与外层装饰器相结合,要理解使用@语法的时候到底执行了什么,是理解装饰器的关键.

>>> import os
>>> import sys
>>>
>>> def outer2(function2):
def inner2(*args,**kwargs):
print("装饰器2--->【开始】")
ret=function2(*args,**kwargs)
print("装饰器2--->【结束】")
return ret
return inner2 >>> def outer1(function1):
def inner1(*args,**kwargs):
print("装饰器1--->【开始】")
ret=function1(*args,**kwargs)
print("装饰器1--->【结束】")
return ret
return inner1 @outer2
@outer1
def lyshark():
print("lyshark 函数被执行了") #==调用并执行函数,结果如下==========================================
>>> lyshark()
装饰器2--->【开始】
装饰器1--->【开始】
lyshark 函数执行了
装饰器1--->【结束】
装饰器2--->【结束】 #==调用并执行函数,结果如下==========================================
@outer1
@outer2
def lyshark_and():
print("lyshark_and 函数被执行了") >>> lyshark_and()
装饰器1--->【开始】
装饰器2--->【开始】
lyshark_and 函数执行了
装饰器2--->【结束】
装饰器1--->【结束】

6.3 带参装饰器

前面的装饰器本身没有带参数,如果要写一个带参数的装饰器怎么办,那么我们就需要写一个三层的装饰器,而且前面写的装饰器都不太规范,下面来写一个比较规范带参数的装饰器,下面来看一下代码,大家可以将下面的代码自我运行一下.

给装饰器本身添加参数: 接下来我们将给装饰器本身添加一些参数,使其能够实现参数传递.

>>> import functools
>>> import sys
>>>
>>> def lyshark(temp=""): #指定装饰器默认参数
def decorator(function): #定义装饰器
@functools.wraps(function) #使被装饰的装饰器的函数名不改变
def wrapper(*args,**kwargs):
print("主函数开始执行前,会先执行我!")
print("{}:{}".format(temp,function.__name__)) #这里调用了装饰器temp变量
ret=function(*args,**kwargs)
print("主函数执行结束后,要在执行我!")
return ret
return wrapper
return decorator #==调用并执行函数,结果如下==========================================
>>> #如果不给装饰器加参数,那么这个装饰器将使用默认参数 temp="",来填充
>>> @lyshark()
def test(x):
print(x+100) >>> test(100)
主函数开始执行前,会先执行我!
:test #这里由于没有传递参数则第一项为空,第二项是函数名称`function.__name__`取出的
主函数执行结束后,要在执行我! #==调用并执行函数,结果如下==========================================
>>> #下面是给装饰器一个参数,将不是用默认参数 temp="",将变成 temp="LyShark"
>>> @lyshark("LyShark")
def test(x):
print(x+100) >>> test(100)
主函数开始执行前,会先执行我!
LyShark:test
主函数执行结束后,要在执行我!

给装饰器本身添加参数: 接下来我们将给装饰器本身添加两个参数,使其能够传递多个参数.

>>> import sys
>>> import os
>>>
>>> def lyshark(x="Hello",y="LyShark"):
def decorator(function):
def wrapper():
print("主函数执行前,应先执行我!")
print(x,y)
ret=function()
print("主函数执行后,要执行我!")
return ret
return wrapper
return decorator #==调用并执行函数,结果如下==========================================
>>> #使用默认参数的装饰器:此时 x="Hello" y="LyShark"
>>> @lyshark()
def test():
print("我是test(),主函数,装饰器在装饰我") >>> test()
主函数执行前,应先执行我!
Hello LyShark
我是test(),主函数,装饰器在装饰我
主函数执行后,要执行我! #==调用并执行函数,结果如下==========================================
>>> #给装饰器指定参数:此时 x="My Name Is :" y="LyShark"
>>> @lyshark("My Name Is :","LyShark")
def test():
print("我是test(),主函数,装饰器在装饰我") >>> test()
主函数执行前,应先执行我!
My Name Is : LyShark
我是test(),主函数,装饰器在装饰我
主函数执行后,要执行我!

6.0 Python 使用函数装饰器的更多相关文章

  1. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  2. Decorator——Python初级函数装饰器

    最近想整一整数据分析,在看一本关于数据分析的书中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)装饰器. 先简单描述一下前两点,再详细解说Python初级的函数 ...

  3. python基础-----函数/装饰器

    函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...

  4. python 复习函数 装饰器

    # 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...

  5. day11 python之函数装饰器

    一,什么是装饰器? 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事 ...

  6. python 匿名函数&装饰器

    匿名函数 关键字lambda表示匿名函数,冒号前面的x表示函数参数匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. >>> list(map(l ...

  7. python闭包函数&装饰器

    一.函数引用 函数可以被引用 函数可以被赋值给一个变量 def hogwarts(): print("hogwarts") # hogwarts() # 函数调用 print(ho ...

  8. Python之函数装饰器

    在实际中,我们可能需要在不改变函数源代码和调用方式的情况下,为函数添加一些新的附加功能,能够实现这种功能的函数我们将其称之为装饰器.装饰器本质上其实还是是一个函数,用来装饰其它函数,为函数添加一些附加 ...

  9. python 之 函数 装饰器

    5.8 装饰器 1 开放封闭原则 软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的 也就是说我们必须找到一种解决方案: 能够在不修改一个功能源代码以及调用方式的前提 ...

  10. Python中函数装饰器及练习

    )])   ,,],)

随机推荐

  1. AIGC

    博客目录 本地部署modelscope-agent python 使用 Google Gemini API MetaGPT MetaGPT day01: MetaGPT作者代码走读.软件公司初始示例

  2. 查看公网出口ip

    curl cip.cc curl http://members.3322.org/dyndns/getip curl icanhazip.com curl ident.me curl ifconfig ...

  3. Docker--镜像&&容器基本操作

    1 基础镜像 BusyBox 一个极简版的Linux系统 集成了100多种常用Linux命令 大小不到2MB 适用于简单测试场景 Alpine 一个面向安全的轻型Linux发行版系统 比BusyBox ...

  4. mysql--ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

    问题背景: 1.在授权机器上连接mysql 8.0的数据库,账号.密码都没有问题,报错 2.使用 navicat工具连接8.0版本,报错 排查思路: 可能是创建用户没有指定插件使用了8.0自带的插件, ...

  5. CO01生产订单屏幕增强

    一.生产订单客户屏幕新增字段 二.生产订单抬头AUFK表的CI_AUFK中新增屏幕字段 三.CMOD 增强分配PPCO0012 修改0100屏幕,新增对应字段,其中生产订单类型设置为下拉框 EXIT_ ...

  6. 我的2023年度关键词:ChatGPT、生产力工具

    2023 是 AI 大爆发的一年,这一年我在我的生产力工具中(一个叫 lowcode 的 vscode 插件)接入了 ChatGPT API,插件也进行了重构,日常搬砖也因为 ChatGPT 的引入发 ...

  7. 3 分钟将免费无限制的 Claude 2.0 接入任意 GPT 套壳应用,太香了!

    Claude 是 ChatGPT 的最强竞争对手,由 OpenAI 早期团队成员创建,目标就是打造出能 赶超 ChatGPT 的 AI.最新版的 Claude 2.0,能力已经开始领先 ChatGPT ...

  8. 用C#实现最小二乘法(用OxyPlot绘图)✨

    最小二乘法介绍 最小二乘法(Least Squares Method)是一种常见的数学优化技术,广泛应用于数据拟合.回归分析和参数估计等领域.其目标是通过最小化残差平方和来找到一组参数,使得模型预测值 ...

  9. docker 资源限制之 cgroup

    1. Liunx cgroup 使用 namespace 隔离运行环境,使得进程像在独立环境中运行一样.然而,仅有隔离环境还不够,还得限制被 namespace 隔离的资源.否则,namespace ...

  10. 一个WPF开发的打印对话框-PrintDialogX

    今天五月一号,大家玩的开心哦. 1. 介绍 今天介绍一个WPF开发的打印对话框开源项目-PrintDialogX,该开源项目由<WPF开源项目:AIStudio.Wpf.AClient>作 ...