首页 > 编程语言 >6.0 Python 使用函数装饰器

6.0 Python 使用函数装饰器

时间:2023-08-14 15:36:56浏览次数:39  
标签:函数 Python lyshark 6.0 print 执行 装饰 def

装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为"装饰器"(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(),主函数,装饰器在装饰我
主函数执行后,要执行我!

本文作者: 王瑞 本文链接: https://www.lyshark.com/post/63fd2e5b.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

标签:函数,Python,lyshark,6.0,print,执行,装饰,def
From: https://blog.51cto.com/lyshark/7077529

相关文章

  • 7.0 Python 面向对象编程
    python是一种面向对象的编程语言,面向对象编程(Object-OrientedProgramming,OOP)是一种编程思想,其核心概念是“对象”。对象是指一个具有特定属性和行为的实体,而面向对象编程就是通过对这些实体进行抽象、分类、封装和继承等操作,来实现程序的结构和逻辑。在python中,我们可以通过定义类......
  • 9.0 Python 内置模块应用
    Python是一种高级、面向对象、通用的编程语言,由GuidovanRossum发明,于1991年首次发布。Python的设计哲学强调代码的可读性和简洁性,同时也非常适合于大型项目的开发。Python语言被广泛用于Web开发、科学计算、人工智能、自动化测试、游戏开发等各个领域,并且拥有丰富的第三方库......
  • 8.0 Python 使用进程与线程
    python进程与线程是并发编程的两种常见方式。进程是操作系统中的一个基本概念,表示程序在操作系统中的一次执行过程,拥有独立的地址空间、资源、优先级等属性。线程是进程中的一条执行路径,可以看做是轻量级的进程,与同一个进程中的其他线程共享相同的地址空间和资源。线程和进程都可......
  • 6.0 Python 使用函数装饰器
    装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为"装饰器"(Decorator),装饰器的功能非常强大,装饰器一般接受一个函数对象作为参数,以对其进行增强,相当于C++中的构造函数,与析构函数。装饰器本质上是一个python函数,它可以让其他函......
  • Python基础day65 BBS个人博客项目完整搭建
    BBS-个人博客项目的完整搭建项目开发流程一、项目分类现在互联网公司需要开发的主流web项目一般分为两类:面向互联网用户,和公司内部管理。面向互联网用户:C(consumer)端项目公司内部管理:B(business)端项目还有一类web应用,基本采用基于角色的权限控制,不同的员工在这套系统......
  • 软件测试|Python科学计算神器numpy教程(五)
    NumPy的高级索引功能前言NumPy是Python中最受欢迎的科学计算库之一,它提供了丰富的功能来处理和操作数组数据。在本文中,我们将深入了解NumPy的高级索引功能,这些功能允许我们根据特定条件或索引数组来访问和修改数组的元素,为数据科学和数组操作提供了更大的灵活性和控制力。NumP......
  • 软件测试|Python科学计算神器numpy教程(六)
    NumPy的广播机制前言NumPy是Python中最受欢迎的科学计算库之一,它提供了高性能的多维数组对象和丰富的数组操作功能。其中,广播机制是NumPy的重要特性之一,它允许不同形状的数组进行算术运算,提供了灵活而高效的数组操作能力。在本文中,我们将深入探讨NumPy的广播机制,以便更好地理解......
  • Python实现透明隧道代理:不影响现有网络结构
    作为一名专业爬虫程序员,我们常常需要使用隧道代理来保护个人隐私和访问互联网资源。本文将分享如何使用Python实现透明隧道代理,以便在保护隐私的同时不影响现有网络结构。通过实际操作示例和专业的解析,我们将带您深入了解透明隧道代理的工作原理,并提供实用的操作价值。首先了解一下......
  • IronPython内存释放问题
    先给出优化后的代码:varoptions=newDictionary<string,object>{["LightweightScopes"]=true};ScriptEngineeng=IronPython.Hosting.Python.CreateEngine(AppDomain.CurrentDomain,options);varscope=eng.CreateScope();using(varstreamOut=n......
  • python语言学习-------------------------------------csv模块将有规律的分隔符去掉,转
    上代码:importcsvf=open("C:/Users/Administrator/Desktop/11.txt",'r')withf:reader=csv.reader(f,delimiter=",")forrowinreader:foreinrow:print(e)实现效果如下: G:\Python3.8解释器\python.exeC:/U......