zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    A1066 Root of AVL Tree (25 分)
    A1099 Build A Binary Search Tree (30 分)
    A1043 Is It a Binary Search Tree (25 分) ——PA, 24/25, 先记录思路
    A1079; A1090; A1004:一般树遍历
    A1053 Path of Equal Weight (30 分)
    A1086 Tree Traversals Again (25 分)
    A1020 Tree Traversals (25 分)
    A1091 Acute Stroke (30 分)
    A1103 Integer Factorization (30 分)
    A1032 Sharing (25 分)
  • 原文地址:https://www.cnblogs.com/zanao/p/11079840.html
Copyright © 2011-2022 走看看