zoukankan      html  css  js  c++  java
  • Python 装饰器

    装饰器函数

    #装饰器:在不改变函数的调用方式的情况下,给函数的前后添加新的功能。#

    有的时候写完一段代码,过段时间需要对它进行升级、添加一些新功能,但是如果要直接修改原来的代码会影响其他人的调用,所以就需要一个不修改源代码且不修改原函数的调用方式的东西,又能为原函数增添新功能的东西,装饰器就是干这个的。(装饰器的本质其实是个闭包函数)

    ##复习:闭包;内部函数使用外部函数中的变量,这种情况下就称这是一个闭包。

    def f1(b):
        def f2():
            print(b)
        f2()
        return f2
    ff=f1('bbb')
    ff()
    # bbb
    # bbb
    

     

    ####上例中timer()就是一个装饰器函数,f()就是被装饰函数

    1)为什么要用装饰器

    #开放封闭原则:对修改封闭,对扩展开放

    2)什么是装饰器

    装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
    强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
    装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

     原则: 开放封闭原则  

       开放 : 对扩展是开放的
    封闭 : 对修改是封闭
    # timmer就是一个装饰器函数,对一个函数 有一些装饰作用
    import time
    def timmer(f):    #装饰器函数
        def inner():
            start = time.time()
            ret = f()       #被装饰的函数
            end = time.time()
            print(end - start)
            return ret
        return inner
    
    @timmer         #语法糖 @装饰器函数名
    def func():     #被装饰的函数
        time.sleep(0.01)
        print('老板好同事好大家好')
        return '新年好'
    # func = timmer(func)
    ret = func()   #inner()
    print(ret)
    ###
    老板好同事好大家好
    0.010995864868164062
    新年好

    3)装饰带参数函数的装饰器

    import time
    def timmer(f):    #装饰器函数
        def inner(*args,**kwargs):
            #(1,2) /(1)
            start = time.time()
            ret = f(*args,**kwargs)  #f(1,2)       #被装饰的函数
            end = time.time()
            print(end - start)
            return ret
        return inner
    
    @timmer         #语法糖 @装饰器函数名
    def func(a,b):     #被装饰的函数
        time.sleep(0.01)
        print('老板好同事好大家好',a,b)
        return '新年好'
    # func = timmer(func)
    ret = func(1,2)   #inner()
    ret = func(1,b = 2)   #inner()
    print(ret)
    
    #####
    老板好同事好大家好 1 2
    0.030028820037841797
    老板好同事好大家好 1 2
    0.010994195938110352
    新年好

    4)装饰器的固定格式

    def wrapper(f):    #装饰器函数
        def inner(*args,**kwargs):
            '''被装饰函数之前加的内容'''
            ret = f(*args,**kwargs) #被装饰的函数
            '''被装饰函数之后加的内容'''
            return ret
        return inner
    
    @wrapper         #语法糖 @装饰器函数名
    def func():     #被装饰的函数
        time.sleep(0.01)
        print('老板好同事好大家好')
        return '新年好'
    
    ret = func()
    #温故而知新
    def wrapper(func):
        def inner(*args,**kwargs): #接收参数时将参数聚合 inner((3))
            print("在被装饰函数之前加的内容")
            ret = func(*args,**kwargs)#调用函数时将参数打散 holiday(*(3),**{})
            print("在被装饰函数之后加的内容")
            return ret
        return inner
    @wrapper # holidy = wrapper(holiday)
    def holiday(day):
        print("全体放假%d天" %day)
        return "Happy!"
    ret = holiday(3) #inner(3)print(ret)
    
    ####
    在被装饰函数之前加的内容
    全体放假3天
    在被装饰函数之后加的内容
    Happy!

    5) wraps

    def span():
        '''打印一个字符串的函数
        ::return:
        '''
        print("Python_Test!")
    print(span.__name__) # 查看字符串格式的函数名
    print(span.__doc__) # document
    
    #######
    span
    打印一个字符串的函数
        ::return:

    ##################################################
    from
    functools import wraps #导入wraps装饰器 def wrapper(func): #func = holiday @wraps(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 '好开心' print(holiday.__name__) #查看字符串格式的函数名 print(holiday.__doc__) #document ret = holiday(3) #inner print(ret)

    ###

    holiday
    这是一个放假通知
    在被装饰的函数执行之前做的事
    全体放假3天
    在被装饰的函数执行之后做的事
    好开心

    ###################################################

     ###三层装饰器

    import time
    FLAG = False                #定义全局变量
    def timmer_out(flag):
        def timmer(func):
            def inner(*args,**kwargs):
                if flag:
                    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 = timmer_out(FLAG)
    @timmer_out(FLAG)    #wahaha = timmer(wahaha)
    def wahaha():
        time.sleep(0.1)
        print('wahahahahahaha')
    
    @timmer_out(FLAG)
    def erguotou():
        time.sleep(0.1)
        print('erguotoutoutou')
    
    wahaha()
    erguotou()

     ##温故而知新(带参数的装饰器)

    import time
    FLAG = True
    def timmer_out(flag):
        def timmer(func):
            def inner(*args,**kwargs):
                if flag:
                    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(FLAG)
    def func1():
        time.sleep(0.1)
        print("Happy1111")
        return "呵呵呵!!!"
    
    @timmer_out(FLAG)
    def func2():
        time.sleep(0.1)
        print("Happy2222")
        return "哈哈哈!!!"
    
    func1()
    func2()
    
    #####
    Happy1111
    0.10094833374023438
    Happy2222
    0.1000070571899414

     6)多个装饰器装饰同一个函数

    def wrapper3(func):
        def inner3():
            print("In wrapper3 ,before func")
            ret = func()
            print("In wrapper3 ,after func")
            return ret
        return inner3
    
    @wrapper3
    @wrapper2
    @wrapper1
    def f():
        print("This is a f")
        return "万能装饰器!"
    
    print(f())
    
    ###########
    In wrapper3 ,before func
    In wrapper2 ,before func
    In wrapper1 ,before func
    This is a f
    In wrapper1 ,after func
    In wrapper2 ,after func
    In wrapper3 ,after func
    万能装饰器!
     
  • 相关阅读:
    Docker系列二:Docker的基本结构
    Codeforces 1013
    树形结构升级
    Codeforces 402 and 403 (Div. 2 and 1)
    Codeforces 342
    图论基础
    树形结构基础
    Codeforces 788 (Div. 1)
    NOIP/CSP-J/S初赛集锦
    树的重心
  • 原文地址:https://www.cnblogs.com/shaopan/p/10003966.html
Copyright © 2011-2022 走看看