zoukankan      html  css  js  c++  java
  • day 12

    装饰器进阶

    装饰器的简单回顾

    装饰器
    开发原则:开放封闭原则
    装饰器的作用:在不改变原函数的调用方式的情况下,在函数的前后添加功能
    装饰器的本质:闭包函数

    装饰器的模式

    def wrapper(func):
        def inner(*args,**kwargs):
            print("在被装饰的函数执行之前做的事")
            ret =func(*args,**kwargs)
            print("在被装饰的函数执行之前做的事")
            return ret
        return inner
    
    @wrapper    #holiday = wrapper(holiday)
    def holiday(day):
        print("放假休息 %s 天"%day)
        return '好开心'
    
    ret = holiday(3)
    print(ret)

    我们来看两个双下方法:__name__ 、__doc__

    def wahaha():
       '''
       一个打印娃哈哈的函数
       '''
       print('娃哈哈')
    
    print(wahaha.__name__)  #查看字符串格式的函数名
    print(wahaha.__doc__)     #document 显示函数的注释(限于多行注释)
    #输出结果:
    '''
    wahaha
    
       一个打印娃哈哈的函数
    
    '''

    接下来是 wraps 函数

    from functools import wraps  #引用 wraps 函数
    
    def wrapper(func):
        #wraps() 加在最内层函数正上方
        #@wraps(func)   #在不使用 wraps 函数时 返回结果: inner  inner 函数的注释
        @wraps(func)    #使用 wraps 函数来装饰 inner 函数 返回结果:holiday  只是一个放假通知
        def inner(*args,**kwargs):
            '''
             inner 函数的注释
            '''
            print("在被装饰的函数执行之前做的事")
            ret =func(*args,**kwargs)
            print("在被装饰的函数执行之前做的事")
            return ret
        return inner
    
    @wrapper    #holiday = wrapper(holiday)
    def holiday(day):
        '''
        只是一个放假通知
        '''
        print("放假休息 %s 天"%day)
        return '好开心'
    
    print(holiday.__name__)  #当不调用 wraps 函数时,显示的为 inner 函数的名称
    print(holiday.__doc__)   #当不调用 wraps 函数时,显示的为 inner 函数的注释
    
    ret = holiday(3)    #在使用装饰器 wraps 函数时,并不影响 holiday 函数的使用
    print(ret)          #这正是装饰器函数的特点
    # 返回结果:
    '''
    在被装饰的函数执行之前做的事
    放假休息 3 天
    在被装饰的函数执行之前做的事
    好开心
    '''

    假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
    一个一个的取消掉? 没日没夜忙活3天。。。
    过两天领导想通了,再让你加上。。。

    #装饰器的三层嵌套 为的是给装饰器传入变量
    import time
    #flage = False  #此处控制执行与否
    flage = True
    def timmer_out(flag):
        def timmer(func):
            def inner(*args,**kwargs):
                if flage:
                    start = time.time()
                    ret = func(*args,**kwargs)
                    end = time.time()
                    print(end - start)
                    return ret
                else:
                    ret = func(*args,**kwargs)
                    return ret
            return inner
        return timmer
    
    @timmer_out(flage)  #timmer_out(flage) 表示 timmer_out(flage) == timmer
    def func():         #@ 表示 @timmer 即:func == timmer(func)
        time.sleep(0.1)
        print("结束")
    
    @timmer_out(flage)
    def func2():
        time.sleep(0.1)
        print("结束")
    
    func()
    func2()

    多个装饰器,装饰一个函数

    def wrapper(func):
        def inner(*args,**kwargs):
            print("-----1-----")
            ret = func(*args,**kwargs)
            print("*****1*****")
            return ret
        return inner
    
    def wrapper2(func):
        def inner2(*args,**kwargs):
            print("-----2-----")
            ret = func(*args,**kwargs)
            print("*****2*****")
            return ret
        return inner2
    
    def wrapper3(func):
        def inner3(*args,**kwargs):
            print("-----3-----")
            ret = func(*args,**kwargs)
            print("*****3*****")
            return ret
        return inner3
    
    @wrapper3
    @wrapper2
    @wrapper
    def f():
        print("in f")
        return '就是这样'
    print(f())
    输出结果如下:
    -----3-----
    -----2-----
    -----1-----
    in f
    *****1*****
    *****2*****
    *****3*****
    就是这样

    执行过成可参考下图

    Python类中的装饰器在当前类中的声明与调用

    class Test():
        xx = False
    
        def __init__(self):
            pass
    
        def test(func):
            def wrapper(self, *args, **kwargs):
                # print(self.xx)
                return func(self, *args, **kwargs)
    
            return wrapper
    
        @test
        def test_a(self, a, b):
            print(f'ok,{a} {b}')    # ok,12 13
    
    
    t = Test()
    t.test_a(12, 13)

    注意:

    1. 其中装饰器test是在类Test中声明并在其方法test_a中调用

    2. 装饰器test内层wrapper函数的首参数是self

    参考资料:

    1. Python decorators in classes

  • 相关阅读:
    文件操作
    xadmin的使用
    Vue
    Redis
    Django
    python小结
    利用线程池和回调函数爬虫
    drf-基表、断关联表关系、级联删除、正方向查询、子序列化
    drf序列化
    drf初识
  • 原文地址:https://www.cnblogs.com/ysging/p/10068358.html
Copyright © 2011-2022 走看看