• python进阶系列 - 12 装饰器


    装饰器的目的是为了扩展函数的功能,而不是修改函数本身。 它是一个非常强大的工具,它允许为现有的函数添加新的功能。

    本文主要分享有两种装饰器:

    • 函数装饰器
    • 类装饰器

    一个函数可以被修饰为一个装饰器,使用 @ 号。

    示列代码:

    @my_decorator
    def my_function():
        pass
    
    • 1
    • 2
    • 3

    看完上面的示例代码,我们再来看看这个函数是如何被修饰的。

    函数装饰器

    为了理解装饰器模式,我们需要先强调下Python中一切都皆为对象。

    函数也是一种对象,它可以被赋值给变量,还可以在另一个函数内定义,作为另一个函数的参数,或者从另一个函数返回。

    装饰器是一个接受另一个函数作为参数的函数,它包装了函数的行为,并返回包装后的函数。所以装饰器的目的是为了扩展函数的功能,而不是修改函数本身。

    练习下面代码:

    def start_end_decorator(func):
        def wrapper():
            print("Start")
            func()
            print("End")
    
        return wrapper
    
    
    def print_name():
        print("Alex")
    
    
    print_name()
    print()
    # 使用装饰器得到一个新的函数
    print_name_new = start_end_decorator(print_name)
    print_name_new()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果:

    Alex
    
    Start
    Alex
    End
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解释

    上面的代码中定义了两个函数,其中print_name()函数是一个普通函数,它的功能是打印Alex

    我们重点来看start_end_decorator()函数:

    1. 它的参数func是一个函数。
    2. 它在内部定义了一个函数wrapper()作为返回值。当然wrapper就是一个名字而已,可以随意😊。
    3. wrapper()首先打印出"Start",然后调用func(),最后打印"End"。

    总起来看,start_end_decorator()函数的是扩展了print_name()函数的功能:

    • 在其运行之前打印Start,
    • 运行结束之后打印End。

    所以我们可以用start_end_decorator()函数来修饰print_name()函数,得到一个新的函数print_name_new

    思考题,请写一个装饰器函数,来打印函数的执行时长。

    装饰器的语法

    上面的函数我们必须重新定义一个函数,这比较麻烦,所以Python提供了一种语法来定义装饰器。 它可以将修饰后函数赋值给自己,我们可以通过@修饰我们的函数来实现相同的功能。

    请练习下面代码:

    def start_end_decorator(func):
        def wrapper():
            print("Start")
            func()
            print("End")
    
        return wrapper
    
    
    @start_end_decorator
    def print_name():
        print('Alex')
    
    
    print_name()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:

    Start
    Alex
    End
    
    • 1
    • 2
    • 3

    解释

    首先我们定义了一个装饰器start_end_decorator()。 然后在定义新的函数print_name()时,我们使用了@装饰器。 从而print_name()函数具备了新的功能!

    是不是@非常简单,这也是真实工作中最常用的!!!

    修饰带参数的函数

    如果我们的函数有输入参数,上面的装饰器就无法实现,因为Python不允许装饰器接受参数。

    那我们该怎么办呢?

    我们可以在内部函数中使用 *args**kwargs 来实现。

    请尝试下面代码:

    def start_end_decorator_2(func<
    • 相关阅读:
      SPC 统计过程控制
      测试用例需要哪些人来评审?如何高效评审?
      simulink求解器选择的小tip
      Linux学习笔记(3)
      基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)
      为什么使用命令行
      一文读懂vue3的Pinia
      绿盟安全事件响应观察及远程代码执行漏洞
      chatgpt
      C的魅力在于指针
    • 原文地址:https://blog.csdn.net/pythontip/article/details/126752548