• 五、装饰器


    一、装饰器

    定义:修改其他函数功能的函数

    意义:让其他函数在不修改任何代码的前提下增加其他额外的功能(比如手机壳,在不修改手机的情况下,增加手机的美观。颜色等)。不用装饰器的函数是永久性的修改,用了装饰器是函数可随时修改

    举例1:

    def add(a,b):
        return a + b
    
    def new_add(add,*args,**kwargs):
        return f'<{add(*args, **kwargs)}>'
    
    if __name__ == '__main__':
         print(f'<{add(1,1)}>')   #没有装饰器new_add时  <2>
         print(new_add(add, 1, 1))  #使用装饰器时  <2>

    举例2:

    def text():
        return "Hello world"
    
    def add_itali(func):
        def wrapper():
            return f"<i>{func()}<i>"
        return wrapper
    
    if __name__ == '__main__':
        print(add_itali(text)())  #结果: <i>Hello world<i>

    使用注解符是装饰器使用更加方便:

    # 先定义装饰器
    def add_itali(func):
        def wrapper():
            return f"<i>{func()}<i>"
        return wrapper
    
    #使用 @装饰器函数名 方式
    @add_itali
    def text():
        return "Hello world"
    
    if __name__ == '__main__':
        print(text())  # <i>Hello world<i>

     多个装饰器时,可在函数上加多个装饰符

    def add_itali(func):
        '''加粗'''
        def wrapper():
            return f"<i>{func()}<i>"
        return wrapper
    
    def add_bold(func):
        '''倾斜'''
        def wrapper():
            return f"<b>{func()}<b>"
        return wrapper
    
    @add_itali
    @add_bold
    def text():
        return "Hello world"
    
    if __name__ == '__main__':
        print(text())  # <i><b>Hello world<b><i>

    注意:调换@add_itali   @add_bold的位置,查看结果:<b><i>Hello world<i><b>

    举例3:

    import logging
    import time
    
    def log(func):
        def wrapper(*args, **kwargs):
            logging.info(f'{func.__name__} is running....')
            return func(*args, **kwargs)
        return wrapper
    
    def calc_time(func):
        def wrapper(*args, **kwargs):
            start = time.time()
            func(*args, **kwargs)
            end = time.time()
            print(f'{func.__name__} 运行了{end-start}时间')
            return func(*args, **kwargs)
        return wrapper
    
    @log
    @calc_time
    def add(a,b):
        return a + b
    
    if __name__ == '__main__':
        add(1, 3)

    装饰器格式:

    装饰器就是一个函数

    def 装饰器名(func):
      def wrapper(*args, **kwargs):
        //要做的装饰,此处省略若干代码
        return func(*args, **kwargs)
      return wrapper

    二、类的装饰器

    作用:用来装饰类

    def 装饰器名(cls):
        //装饰代码若干
        return cls

    举例1:

    def add_name(cls):
        cls.name = "zjx"
        return cls
    
    @add_name
    class A(object):
        pass
    
    if __name__ == '__main__':
        a = A()
        print(a.name)  #结果: zjx

    三、装饰器类

    这个装饰器不是一个函数,而是一个类

    格式如下:

    class 装饰器名(object):
        def __init__(self,func):
            self.func = func
            
        def __call__(self, *args, **kwargs):
            pass # 写装饰代码
            return self.func(*args, **kwargs)

    _ _call_ _方法:函数的调用,实际就是调用函数里的_ _call_ _方法

    举例:

    class A(object):
        def __init__(self,func):
            self.func = func
    
        def __call__(self, *args, **kwargs):
            print("call is running.....")
            result = self.func(*args, **kwargs)
            return result
    @A
    def add(a,b):
        return a + b
    
    if __name__ == '__main__':
        print(add(1,3))   
    ''' call is running..... 4 '''

    注意:调用类的对象,__call__会自动被调用

    四、带参数的装饰器

    如:@log(filename='text.log')

    # 带参数的装饰器-三层函数(最外层用来传参)---装饰器里面可以传参数
    # @log(filename = "123.txt")
    
    import logging
    
    def add_log(filename):       # 最外层:接收装饰参数
        def inner(func):         # 中间层:接收被装饰函数
            def wrapper(*args, **kwargs):  # 内层装饰函数:接收被装饰的函数的参数
                logging.warning(f"{func.__name__}函数正在被调用...")
                result = func(*args, **kwargs)  # 调用被装饰函数
                return result   # 把被装饰的函数的运行结果返回
            return wrapper
        return inner
    
    
    @add_log(filename="123.txt")
    def add(a, b):
        return a + b
    
    if __name__ == '__main__':
        print(add(3,4))
    """
    WARNING:root:add函数正在被调用...
    7
    """

      

  • 相关阅读:
    用价值链分析软件开发及杂感
    《恰如其分的软件架构》笔记摘要
    观察者模式
    Js中Date对象
    Js中Currying的应用
    read命令
    模板方法模式
    两两交换链表中的节点
    享元模式
    Js中Array对象
  • 原文地址:https://www.cnblogs.com/zhangjx2457/p/14051827.html
Copyright © 2020-2023  润新知