zoukankan      html  css  js  c++  java
  • python_之无参装饰器_01

    # 1:提问:什么是装饰器?
    #   解答:根据字面意思可以理解,装饰器就是用来装饰函数的工具。
    #
    # 2:装饰器有什么特点?
    #   解答:(1) 装饰器原则:开放封闭原则。 解释==》开放是指,对外开放,封闭是指:不修改原代码。
    #      (2) 特点1:给被装饰函数添加新功能
    #      (3) 特点2: 调用被装饰函数
    #
    # 3:小案例: 给index()函数加上计时器

    # import time
    # def index(name):
    # print(f"欢迎{name}来到这里")
    # return "我是index的返回值"
    #
    # def home(name):
    # print(f"欢迎{name}回家了")

    # (1) 不改变源代码,不改变调用方式
    # start_time = time.time()
    # index("madison")
    # sto_time = time.time()

    # 问题1==》如果项目中有很多地方调用的话,会出现代码冗余的问题。==》优化方案如下:封装它
    # 这样一来,我们就解决了代码冗余问题:

    # def wrapper():
    # start_time = time.time()
    # index("madison")
    # stop_time = time.time()

    # 问题2:虽说解决了代码冗余问题,但是我们这里index()的参数写死了,
    # 并且这个装饰器里面的调用的函数写死了

    # 只能调用index(),如果还有一个功能home()怎么办?
    # 优化方案如下 ==》
    # (1):解决传参问题 ==》 利用(*args, **keargs) 进行传参和解包
    # (2):解决index()函数写死问题,利用闭包传参
    # import time
    # def outter(func):
    # def wrapper(*args, **kwargs):
    # start_time = time.time()
    # func(*args, **kwargs) # 对传进来的参数进行解包!
    # stop_time = time.time()
    # return wrapper # 返回wrapper的内存地址
    #
    # wrapper = outter(index)
    # wrapper("madison")
    # print("====================")
    # wrapper = outter(home) # 在试试调用home上面忘记试了,看好不好使
    # wrapper("madison")
    # 这里我解释下:return wrapper是因为,wrapper之前是全局变量,现在被我们写成局部变量了,
    # 所以在这里

    # 我们需要把它变回去,所以我们就返回它的内存地址,
    # 上面我们调用outter(index)就是得到的wrapper的内存

    # 地址,这里赋值给wrapper所以此时 wrapper又变回成了全局变量然后传参调用wrapper即可!

    # 问题3:上面我们已经解决了写死函数和传参问题,那么还有个问题就是返回值的问题?
    # 假如index有返回值,怎么办?

    # import time
    # def outter(func):
    # def wrapper(*args, **kwargs):
    # start_time = time.time()
    # res = func(*args, **kwargs) # 对传进来的参数进行解包!
    # stop_time = time.time()
    # return res
    # return wrapper # 返回wrapper的内存地址
    #
    # wrapper = outter(index)
    # print(wrapper("madison"))
    # 优化方式:看上面,我们知道index的返回值这个装饰器内部,它是func=index,所以index返回啥,我们func就返回
    # 啥就可以了,所以就有了上面的 return res,对了你可以试试在wrapper内部不接收打印,结果会是None,原因是因为
    # 我们现在调用的其实是wrapper,而不是index,有的小伙伴可能会蒙蔽,我上面明明就是调用的wrapper....这个问题
    # 你要回去了解下闭包原理了(这里第二种传参是闭包原理,不理解最好看一边后在看上面的列子)。其实这里我们可以把
    # wrapper = outter(index)改成 index = outter(index),你看,这样我们是不是就 没有修改源码和调用方式


    # 问题4:上面我们已经做到,不修改源码和调用方式,就做了一个装饰功能,但是还有问题,我们每次调用的时候都要去定义
    # wrapper = outter(index)/# wrapper = outter(home),我们需要优化下,方法是:@(语法糖的意思,甜甜
    # 的嘿嘿。)
    import time
    def outter(func):
    def wrapper(*args, **kwargs):
    start_time = time.time()
    res = func(*args, **kwargs) # 对传进来的参数进行解包!
    stop_time = time.time()
    return res
    return wrapper # 返回wrapper的内存地址

    # index = outter(index)
    # print(index("madison"))

    # 问题4的优化方案:在我们需要调用装饰器的头上写上 @outter 即可
    @outter
    def index(name):
    print(f"欢迎{name}来到这里")
    return "我是index的返回值"

    @outter # 它在这做了下面几件事
    # 1:调用outter ==> outter()
    # 2: 将被装饰(index)传进去 ==》 outter(index)
    # 3: 赋值给变量,变量名被装饰自己 ==》 index = outter(index)
    def home(name):
    print(f"欢迎{name}回家了")

    最后附上本节的完整代码的图片

    
    

       我这里总结下无参装饰器的模板:


    下一节我们继续补充无参装饰器的知识,和有参装饰器的知识:


     

  • 相关阅读:
    Idea快捷键
    基于LinkedHashMap实现一个基于LRU算法的缓存设计
    SpringBoot整合Mybatis
    MyBatis Generator自动生成代码
    java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
    Dubbo的异步调用
    Jackson的ObjectMapper的简单用法及语法
    mysql实例代码
    6. Z 字形变换
    13. 罗马数字转整数
  • 原文地址:https://www.cnblogs.com/haibaiwuchang/p/13258454.html
Copyright © 2011-2022 走看看