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

    什么是装饰器?

    • 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码修改的提前增加额外功能。
    • 装饰器的返回值也是一个函数对象。
    • 装饰器的作用就是为已经存在的对象添加额外的功能。
    #原函数
    improt time
    
    def foo (): #原函数
        print ("guo hailan")
        time.sleep(2)
    
    def bar():#原函数
        print ("tang qinghua")
        time.sleep(3)

    #需求,在原函数新增一个计时的功能

    实例:

    def foo():
        start = time.time()#获取当前时间    
        print ("guo hailan")
        time.sleep(2)
        end = time.time()
        print ("spend %s"%(end - start))#计算执行用了多长时间
    
    def bar(): 
        start = time.time()()#获取当前时间
        print ("tang qinghua")
        time.sleep(3)
        end = time.time()
        print ("spend %s"%(end - start)
    
    """
    函数虽然实现了功能,但是改变了原来的功能函数,如果是公共函数,修改一旦出错,影响到整个各个功能都出错。
    不允许你动我的原函数,这是封闭原则,还有一个开放原则,虽然你不可以在原功能上修改,但是你可以扩展
    """

    新增功能,重复代码太多

    这样就造成大量雷同的代码,为了减少重复写代码,我们可以这样做,重新定义一个函数,定义一个专门显示时间的函数

    实例:

    def show_time():
        start = time.time()
        foo()#需要计时的函数
        end = time.time()
        print ("spend %s"%(end - start))

    """
    这个函数只能计算foo()函数的时间
    如果要计算bar时间怎么办,又要重建立新的函数呢
    """

    #我们将定义显示时间函数,传一个参数(传入功能函数)计算哪个函数就传入哪个函数名字。

    实例:

    def show_time(f): #f是传入的参数函数
        start = time.time()
        f()  #接受的函数
        end  = time.time()
        print ("spend %s"%(end - start))
     
    show_time(foo)#调用函数
    show_time(bar)
    
    """
    功能是实现了,但是调用方式改变了,之前调用的是foo(),
    所有调用foo()的函数都要跟着改成show_time()
    所有的业务都要跟着改,有点不合理
    """

    问题是怎么不改变调用方式能实现功能。我们的要求是,调用foo()就能实现原函数功能和计时功能。

    我们可以对show_time(foo)赋值,做一个嵌套函数

    def show_time(f): #装饰器函数,(这个函数要放在最前面,因为后面调用的时候需要先存到内存里面)
        def inner():
            start = time.time()
            f()
            end = time.time()
            print ("spend %s"%(end - start))
        return inner #装饰函数返回值是一个函数对象(返回的是inner的内在地址)
    
    foo = show_time(foo) #赋值给foo (这一句要放在原有函数的下面)
    
    
    def foo():
        print ("guo hailan")
        time.sleep()
    foo = show time(foo)
    foo()#执行这个的时候相当于是执行inner函数
    
    '''
    python 提供了一个比较高大上的表示方法@show_time @show_time等价于 foo = show time(foo) @show_time 放在原功能函数的上面 ''' 实例: @show_time() def foo(): print ("guo hailan") time.sleep(3) foo() #函数调用

    功能函数加参数

    实例:

    #功能函数加参数
    def show_time(f): 
        def inner(x,y):
            start = time.time()
            f(x,y)
            end = time.time()
            print ("spend %s"%(end - start))
        return inner 
    
    @show_time() # 等价 add = show_time(add)
    def add(a,b):
        print (a+b)
        time.sleep(3)
    
    add(2,2)

    功能函数传不定长参数

    实例:

    #功能函数传不定长参数
    def show_time(f): 
        def inner(*x,**y):
            start = time.time()
            f(*x,**y)
            end = time.time()
            print ("spend %s"%(end - start))
        return inner 
    @show_time()
    # 等价 add = show_time(add) def add(*a,**b): #功能函数 sums = 0 for i in range(a) sums + = i #等价 sums = sums + i print (sums) time.sleep(3) add(1,3,5,7,9) #这一串传进去给*a

     装饰器加参数

    #装饰器加参数
    def logger(flag="")#加上这个是因为要向外界要个参数进来,默认为空,传true才会打印日志
        def show_time(f): 
            def inner(*x,**y):
                start = time.time()
                f(*x,**y)
                end = time.time()
                print ("spend %s"%(end - start))
                if flag == "true": #必须传true的时候才会打印日志记录
                    print "打印日志记录"
                else:
                    pass
            return inner
        return show_time
    ----------------------------------------------    
    @logger("true")#调用bar的时候需要打印日志,传入参数
    def bar(): #功能函数
        print ("bar....")
        time.sleep(3)
    bar()
    -------------------------------------------
    @logger("eee")#随便传入一个不会打印日志,设置了传true才打印
    def bar(): #功能函数
        print ("bar....")
        time.sleep(3)
    bar()
    ---------------------------------------------
    @logger() #调用add函数的时候不想打印日志,就不传参数
    def add(*a,**b): #功能函数
        sums = 0
        for i in range(a)    
            sums + = i #等价 sums = sums + i
        print (sums)
        time.sleep(3)
    add(1,3,5,7,9)
  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/guog1/p/8278038.html
Copyright © 2011-2022 走看看