• python之装饰器


    一、开放封闭原则

    1. 是什么?

    开放原则

    软件面试时不可能将所有功能都设计好,当前未来一两年的你需要的功能上线,定期更新迭代,对于软件之前写的源代码一般不会修改,对函数里面的代码以及函数的调用方式。在源码不改变的情况下,增加一些额外的功能。

    封闭原则

    不要改变源码

    python中装饰器: 完美的诠释了开放封闭原则

    2. 装饰器的用途

    装饰器就是一个函数: 装饰器本身就是一个函数,他要装饰一个函数在不改变原函数的源码以及调用方式的前提下,给其增加一个额外的功能。

    登录认证,打印日志

    二、初识装饰器

    装饰器格式:

    def test_time(x):
        def inner():
            start_time = time.time()
            x()
            end_time = time.time()
            print(end_time-start_time)
        return inner
    
    @test_time    # index = test_time(index)
    def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
    index()
    

    例题:

    # 1. 写一个代码测试怼怼哥写的函数的执行效率。
    def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
    
    
    print(time.time())
    start_time = time.time()
    index()
    end_time = time.time()
    print(f'此函数的执行效率{end_time-start_time}')
    
    # 2. 主管让你测试小邓,李大象,重复代码太多
    def func1():
        time.sleep(2)
        print('欢迎访问日记首页')
    
    
    def func2():
        time.sleep(1)
        print('欢迎访问评论首页')
    
    start_time = time.time()
    func1()
    end_time = time.time()
    print(f'此函数的执行效率{end_time-start_time}')
    
    start_time = time.time()
    func2()
    end_time = time.time()
    print(f'此函数的执行效率{end_time-start_time}')
    
    # 3. 整合到函数中
    def func1():
        time.sleep(2)
        print('欢迎访问日记首页')
    
    
    def func2():
        time.sleep(1)
        print('欢迎访问评论首页')
    
    
    def test_time(x):
        start_time = time.time()
        x()
        end_time = time.time()
        print(f'此函数的执行效率{end_time-start_time}')
    
    test_time(func1)
    test_time(func2)
    
    # 4. 怼怼哥这个函数在实际项目中被500执行,主管要求:在被执行此函数时,
    同时要测试一下被执行函数的效率。
    
    
    def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
    
    # index()
    def test_time(x):
        start_time = time.time()
        x()
        end_time = time.time()
        print(f'此函数的执行效率{end_time-start_time}')
    
    test_time(index)
    
    版本4的问题: 开放原则满足了,封闭原则:不改变原函数的源码,以及调用方式。
    违反了封闭原则:改变了函数的调用方式。
    
    # 版本5: 不能改变原函数的调用方式(闭包):
    
    
    def index():
        time.sleep(2)
        print('欢迎访问博客园首页')
    
    # index()
    
    # def func1():
    #     time.sleep(2)
    #     print('欢迎访问日记首页')
    
    def test_time(x):  # x = index
        def inner():
            start_time = time.time()
            x()
            end_time = time.time()
            print(f'此函数的执行效率{end_time-start_time}')
        return inner
    
    index = test_time(index)
    index()
    
    # 版本6:被装饰函数有返回值
    
    def test_time(x):  # x = index
        def inner():
            start_time = time.time()
            ret = x()
            # print(F'ret: {ret}')
            end_time = time.time()
            print(f'此函数的执行效率{end_time-start_time}')
            return ret
        return inner
    
    
    @test_time  # index = test_time(index)
    def index():
        time.sleep(0.5)
        print('欢迎访问博客园首页')
        return True
    
    print(index())  # inner()
    你应该是让True返回给index()这样才完美了,但是现在index是inner,所以你要是完全不改变原函数的使用,
    你print(index()) ---> True
    
    
    # 版本7: 被装饰函数带参数,无论加不加装饰器,你的实参'太白金星'应该传给形参n,。
    但版本6不能实现传参,index('太白金星') ==  inner('太白金星')
    
    def test_time(x):  # x = index
        def inner(*args,**kwargs):
            # 函数的定义:* ** 聚合。
            # args = ('苹果')
            #args = (1, 3)
            start_time = time.time()
            ret = x(*args,**kwargs)
            # 函数的执行:* ** 打散。
            # ret = x(*('苹果'))  ==x('苹果',)
            # ret = x(*(1, 3))  ==x(1,3)
            # print(F'ret: {ret}')
            end_time = time.time()
            print(f'此函数的执行效率{end_time-start_time}')
            return ret
        return inner
    
    
    # @test_time  # index = test_time(index)
    def index(n):
        time.sleep(0.5)
        print(f'欢迎{n}访问博客园首页')
        return True
    
    # @test_time  # index = test_time(index)
    def func2(a,b):
        time.sleep(0.5)
        print(f'最终结果:{a+b}')
        return a + b
    
    
    print(index('苹果'))  # inner('苹果')
    print(func2(1,3)) # == inner(1,3)
    
    
    def warpper(f):
        def inner(*args,**kwargs):
            '''被装饰函数之前的操作'''
            # print(666)
            ret = f(*args,**kwargs)
            '''被装饰函数之后的操作'''
            # print('执行完毕了')
            return ret
        return inner
    
    @warpper
    def func():
        print(111)
    #
    func()
    func()
    func()
    func()
    func()
    
    
    装饰器的应用:在不改变原函数的源码以及调用方式前提下,为其增加额外的功能。
    登陆认证,打印日志等。
    
    

    三、被装饰函数带返回值

    带返回值是什么?

    def test_time(x):
        def inner():
            start_time = time.time()
            ret = x() # 我是新加的参数
            end_time = time.time()
            print(end_time-start_time)
            return ret # 我是新加的参数
        return inner
    @test_time
    def func1():
        time.sleep(0.5)
        print('欢迎登录博客园首页')
        return True
    print(func1())
    

    带返回值的目的?

    就是为满足开放封闭原则,使函数更完美

    四、被装饰函数带参数

    是什么?

    函数在不加装饰器的情况下也是要能执行的,加装饰器要不改变原函数的代码

    index('太白金星') == inner('太白金星')

    def test_time(x):  # x = index
        def inner(*args,**kwargs):
            # 函数的定义:* ** 聚合。
            # args = ('苹果')
            #args = (1, 3)
            start_time = time.time()
            ret = x(*args,**kwargs)
            # 函数的执行:* ** 打散。
            # ret = x(*('苹果'))  ==x('苹果',)
            # ret = x(*(1, 3))  ==x(1,3)
            # print(F'ret: {ret}')
            end_time = time.time()
            print(f'此函数的执行效率{end_time-start_time}')
            return ret
        return inner
    
    
    # @test_time  # index = test_time(index)
    def index(n):
        time.sleep(0.5)
        print(f'欢迎{n}访问博客园首页')
        return True
    
    # @test_time  # index = test_time(index)
    def func2(a,b):
        time.sleep(0.5)
        print(f'最终结果:{a+b}')
        return a + b
    
    
    print(index('苹果'))  # inner('苹果')
    print(func2(1,3)) # == inner(1,3)
    

    怎么用?

    五、标准版装饰器

    是什么?

    # 五行
    def warpper(f): #定一个一个外层函数
    	def inner(*args,**wkargs): #定一个内层函数,支持传入参数,在定义时*起聚合的作用,在执行的时候**起打散的作用
    		ret = f(*args,**wkargs)
    		return ret
    	return inner
    
  • 相关阅读:
    快逸报表调用存储过程(SqlServer)
    一个睡五分钟等于六个钟头的方法 (转)
    Windows Live Writer For Windows Server 2003
    设计模式装饰者模式
    SqlServerCUBE
    Android 70道面试题汇总不再愁面试
    说服力:让你的PPT会说话
    亮剑Java项目开发案例导航
    初入社会必知的88个潜规则
    android UI进阶之仿iphone的tab效果2
  • 原文地址:https://www.cnblogs.com/zanao/p/11079840.html
Copyright © 2020-2023  润新知