zoukankan      html  css  js  c++  java
  • py函数装饰器-s

    函数装饰器:

    概念:通过修改其他函数的功能,有助于让代码更简短 原则:已经实现了的功能代码,尽量不修改,对现有的代码进行扩展修改


    下面先简单说几个函数使用的例子:
    例1:
    def f():#假设一个函数f() return "helloworld" #这是默认返回值 print(f()) #调用f()函数并打印。 f1=f #将函数赋值给一个变量,这里没有使用f(),少了括号()的原因是因为这不是调用函数,
          #而是将函数f放到变量f1里面
    print(f1()) #然后来打印一下变量f1的结果,可见f1()会返回函数f的返回值 #====结论:函数可以赋值给变量,通过调用变量,来调用函数


    #例2: def f(): print("first,helloworld") def f1(): return "second,heloworld" def f2(): return "third,helloworld" print(f1()) print(f2()) print(f()) print(f1()) #===结论:函数可以嵌套函数,当函数被调用时,函数内部函数也默认调用并打印,
          #但是直接在函数外调用函数内部的函数却不行,会报错!!!



    #例3: def f(username="qika",pwd="123456"): #给定默认参数username,pwd def f1(): #嵌套2个函数 return "f1,heloworld" def f2(): return "f2,helloworld" if username == "qika" and pwd =="123456": #判断一下:当usernamepwd和默认相等即返回f1,
                                  #不等或其他错误的都返回f2
    return f1 #return f1() else: return f2 #return f2() print(f()) #调用默认的,就会默认传参是username="qika",pwd="123456",并返回f1(函数形式) print(f(11,1)) #传参不为username="qika",pwd="123456",(即传入和预期不符)那么就会返回f2(函数形式) #注意!!!:当上面调用f1f2时,会返回函数,当调用的函数返回值是f1(),f2(),那么就会返回这两个函数下的返回值 #======结论:函数嵌套函数,也可以直接返回函数,也可以返回函数内部的函数的返回值;(多层)

    #例4: def f(): return "first,helloworld" def f2(arg): print("second,helloworld") print("这里打印调用一下:传递进来当做函数参数的函数:{0}".format(arg()))
    f2(f)#直接将上一个函数的函数名传入下一个函数的内当做参数。
    #看懂了吗?简单直白一点: def f3(): print("返回值first") def f4(func): func() f4(f3) #调用:将函数名直接当做函数参数传递使用 #=====结论:函数可以当做参数进行传递使用,方法:将函数名当做参数,直接传递进下一个函数内即可 =====================================================================
    上述,就是函数使用方法的简单总结!







    下面,介绍装饰器使用!!!:
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++ #=============1、对函数使用多个装饰器========== def f(func):#定义函数f print('enter f', func) def f1(): print('running f1') func() return f1 def a(func):#定义函数a print('enter a', func) def a1(): print('running,a1') func() return a1 @f #使用装饰器f,等价于:main=f(main),只是写法不同!!! @a  #使用装饰器a,等价于:main=a(main) def main(): print('running main')
    if __name__ == '__main__': main() #自测,调用一下
         
    #结论:
    装饰器可对一个函数使用多个:
    # 函数main()先被a装饰,变成新的函数,变成另一个函数后,再次被 f 装饰器修饰,不过执行函数是从上至下来的
    #这里主要关注:main()函数被@f和@a所装饰。即等价于:main = f(main),main=a(main)
    就相当于把main函数自己当做参数传入了函数f和a当中,这里只是写法不同!!!

    #===============2、被装饰的函数当作参数,传入装饰器函数内,并调用使用装饰器函数=====================
    '''
    import time

    def show_time(f):#嵌套函数 def inner(*x,**y):#因为下方的add()函数要被装饰,add()函数会被当做参数传入 start = time.time()#到这个函数里面来,因此这里也要传入add()函数中的不定长参数 f(*x,**y) end =time.time() print(end - start) return inner @show_time #使用装饰器函数@show_time,因为我想让show_time()函数在add()也运行使用 def add(*a,**b):#需要传入不定长参数 sums=0 #下面,这里就是add()函数的逻辑了 for i in a: sums +=i print(sums) time.sleep(3)#因为上面的函数要计算时间差,因此我这里延迟一下时间,好看出show_time()函数调用后的时间变化 add(1,2,3,4,5)#调用函数。
    #结论:
    #会先调用add()函数,然后又将add()函数当做参数直接传入到 #上面的show_time函数中去,并再调用show_time()函数。
    (原因:show_time函数装饰了add函数,所以调用本身时,会再去调用装饰器函数show_time。当然前提是装饰器函数满足add函数的条件)


    #=========3、装饰器函数带参数,满足:需要调用就正确传参,不需要调用就不传======================
    import time
    
    def logger(flag):
        def show_time(f):
            def inner(*x,**y):
                start = time.time()
                f(*x,**y)
                end =time.time()
                print(end - start)
                
                if flag == "yes":
                    print("如果使用装饰器函数logger传入了参数,且参数正确等于“yes”,那么就执行这个条件")
    
            return inner
        return show_time
    
    
    #注意了:
    # 因为装饰器函数带有了参数,那么在装饰其他函数时,
    # 参数正确:就会执行装饰器函数里面的判断条件。
    # 如果传入参数不正确(或不传)那么就不会执行装饰器函数里面的那个条件!!!
    @logger("")  #@logger("yes")   如果这样传参为yes,就满足了上面装饰器函数内的参数条件,那么就会执行那个判断条件
    def add(*a,**b):
        sums=0
        for i in a:
            sums +=i
        print(sums)
        time.sleep(3)


    #重要结论:!!!
    #因为有时候会遇到有些函数需要调用这个方法,有些函数不需要调用这个方法,那么怎么办呢?
    #从上可见解决方法,可以使用装饰器函数带参数:
    这样在装饰其他函数时,就可以根据被装饰的函数是否需要调用,进行设置装饰器函数是否传参
    #函数需要调用装饰器函数内的方法或者判断条件时,那么装饰时就传参正确。(反之就可不传,就不会调用了)



    再来引申一下,根据装饰器传参,来选择进行调用不同的方法或条件
    def use_logging(level):
        def decorator(func):
            def wrapper(logging=None, *args, **kwargs):
                if level == "warn":
                    logging.warn("%s is running" % func.__name__)
                elif level == "info":
                    logging.info("%s is running" % func.__name__)
                return func(*args)
            return wrapper
    
        return decorator
    
    @use_logging(level="warn")    #装饰器带参数
    def foo(name='foo'):
        print("i am %s" % name)
    
    foo()
    后面还有函数的内置装饰器介绍:https://www.cnblogs.com/QiKa/p/13532042.html
  • 相关阅读:
    Tomcat内存溢出的三种情况及解决办法分析
    详解:贝叶斯算法(bayesian)在GCMail反垃圾邮件系统中的应用
    关于solr schema.xml 和solrconfig.xml的解释
    Java流操作,InputStream、OutputStream及子类FileInputStream、FileOutputStream;BufferedInpu
    Introduce Null Object(引入Null对象)
    Solr Schema.xml和solrconfig.xml分析
    @InitBinder
    程序员修炼之道
    JSTL 标签库详细介绍资料
    Spring Mvc入门实例
  • 原文地址:https://www.cnblogs.com/QiKa/p/14111105.html
Copyright © 2011-2022 走看看