装饰器

什么是装饰器?

  • 装饰器本质上是一个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)
原文地址:https://www.cnblogs.com/guog1/p/8278038.html