• python学习日记(函数--装饰器)


    楔子

    前提,我有一段代码(一个函数)。

    import time
    def run_time():
        time.sleep(0.1)
        print('我曾踏足山巅')

    需求1:现在,我想计算这段代码的运行时间。

    我可以这样做:

    import time
    def run_time():
        start_time = time.time()
        time.sleep(0.1)
        print('我曾踏足山巅')
        end_time = time.time()
        run_t = end_time - start_time
        print('运行时间为:',run_t)
    run_time()

    此时,需求是可以实现的。

    需求2:不想如此麻烦

    如果有很多个类似的函数需要计算运行时间,那这种方法就会显得特别繁琐。

    我们可以不修改源代码,再定义一个计算时间的函数,将需要被计算时间的函数名作为参数传进去,

    直接调用函数进行计算运行时间,就不需要每个函数里面都加入相同代码了。

    下面进行升级:

    import time
    def run_time():
        time.sleep(0.1)
        print('我曾踏足山巅')
    def run_time1():
        time.sleep(1)
        print('也曾堕入低谷')
    def calculation(f):
        start_time = time.time()
        f()
        end_time = time.time()
        run_t = end_time - start_time
        print('运行时间为:', run_t)
    #直接调用函数进行计算
    calculation(run_time)
    calculation(run_time1)

    需求3:我还想要不修改调用方式直接实现时间的计算。

    即还是直接调用原函数,但是能同时实现原功能以及时间计算的功能。

    由此,我们引入装饰器函数的概念。

    python装饰器

    装饰器的定义

    python装饰器就是用来拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数。

    使用python的好处就是不用更改原函数代码的前提下给函数增加新的功能。

    装饰器的特点

    不修改被装饰函数的调用方式,不修改被装饰函数的源代码。

    实例:实现

    备注:语法糖

    import time
    def run_time(f):       #装饰器函数
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            run_t = end_time - start_time
            print('运行时间为:', run_t)
        return inner
    # func = run_time(func)#不修改函数调用方式,添加新功能
    @run_time#语法糖,代替赋值调用,等价于上一行代码
    def func():
        time.sleep(0.1)
        print('hello world')
    func()

    可以看出,在不改变原函数调用方式的情况下,也实现了运行时间的计算。

    原函数的源码没有改变,调用方式没有改变,并且追加了新的运行时间计算功能。

    装饰器的返回值

    如果被装饰的参数有返回值。

    import time
    #装饰器必定要是一个闭包函数
    def run_time(f):
        def inner():
            start = time.time()
            func_retrun = f() #  func_return = func() 变量接收被装饰函数的返回值
            end = time.time()
            print('被装饰函数运行时间为:',end - start)
            return func_retrun
        return inner
    @run_time
    #被装饰函数
    def func():
        time.sleep(0.1)
        print('hello world')
        return '这是被装饰函数返回值'
    # func = run_time(func) #结果:func = inner
    s = func()
    print(s)

    装饰器的参数

    一、位置参数

    #带有参数的函数装饰器
    def wrapper(f):
        def inner(a):
            print('装饰器增加的额外内容:hello world')
            return f(a)#返回被装饰函数的返回值
            # f(a)
        return inner
    @wrapper
    def func(a):
        print('被装饰函数的参数输入:',a)
        return '被装饰函数的返回值:was a day'
    s = func('once before,a little ...')
    print(s)

    二、默认参数

    #此装饰器 wrapper 实现增加时间戳功能
    import time
    def wrapper(f):
        def inner(a,b,c = 'default'):#在这里加默认参数,还有动态参数亦如是
            print(time.asctime())
            r = f(a,b,c)
            return r
        return inner
    @wrapper
    def func(a,b,c ):
        print(a,b,c)
        return '被修饰函数返回值'
    s = func(1,2)
    print(s)

    三、动态参数

    注:其实下例中的被装饰函数并没有用到参数。不过你可以根据需求自己来进行试验,不再赘述。

    # 此装饰器 wrapper 实现增加时间戳功能
    import time
    def wrapper(f):
        def inner(*args,**kwargs):
            print(time.asctime())
            r = f(*args,**kwargs)
            return r
        return inner
    @wrapper
    def func2():
        print('''    三更灯火五更鸡,
        正是男儿读书时。
        黑发不知勤学早,
        白首方恨读书迟。''')
        r1 =   '''这首诗深入浅出,自然流畅,富含哲理。核心是“黑发早勤学,白首读书迟”。
    从学习的时间这一角度立意,劝勉年轻人不要虚度光阴,要及早努力学习,免得将来后悔。'''
        return r1
    s = func2()
    print(s)

    装饰器的功能和固定结构

    装饰器的主要功能

    在不改变函数调用的基础上在函数的前、后添加功能。

    装饰器的固定结构

    def wrapper(f):#装饰器函数,f是被装饰函数
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            r = f(*args,**kwargs)
            '''执行函数之后要做的'''
            return r#解释器原则,从上至下,返回值最后才进行输出
        return inner
    @wrapper #之后要使用装饰器函数的时候,直接调用就可以了

    pass

    作者:Gruffalo
    ---------------------------------------------
    天行健,君子以自强不息
    地势坤,君子以厚德载物
    内容仅为自己做日常记录,备忘笔记等
    真小白,努力学习ing...一起加油吧!(ง •̀_•́)ง
  • 相关阅读:
    Core1.1环境下,自己实现的一个简单的CRUD框架(反射实现)
    C#反射通过类名的字符串获取生成对应的实例
    在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(续)
    从零开始构建一个的asp.net Core 项目(二)
    从零开始构建一个的asp.net Core 项目(一)
    eNSP自学入门(基础)
    在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(附Git地址)
    Asp .net core api+Entity Framework core 实现数据CRUD数据库中(附Git地址)
    重构--去除丑陋的switch语句
    ASP .NET core 入门基础内容备份
  • 原文地址:https://www.cnblogs.com/smallfoot/p/10028376.html
Copyright © 2020-2023  润新知