python-装饰器

---恢复内容开始---

装饰器:装饰器的本质就是一个函数,其主要目的就是装饰其他函数(为其他函数添加新功能)!

装饰器的一些特性:

  • 不能修改被装饰函数的源代码
  • 被装饰函数的调用方式不能改变

理解以下三点:

  • 函数即变量(函数名可以类比变量名,函数体可以类比变量的内容!)
  • 高阶函数:
    •   把一个函数的函数名作为实参传递给另外一个函数
    •        函数的返回值中包含函数名
#满足两个条件之一的均称为高阶函数# def bar():      #传递函数名作为实参#     print("int the bar...")#
# def outer(func):#     print("in the outer...")#     func()#
# outer(bar)#传递函数名为实参,没有修改被装饰函数的源代码
#返回函数名def bar():  
    print("int the bar...")def outer(func):    print("in the outer...")    return func

bar = outer(bar)
bar()  #返回函数名没有修改原函数的调用方式

 

    •   嵌套函数:在一个函数体中使用def语句定义另一个函数称为嵌套函数,注意不是调用!

装饰器==高阶函数+嵌套函数:

  1. 利用高阶函数(传递函数名为参数的特性)把要被装饰的函数,传递给装饰器函数以添加新的功能,并且不改变被装饰函数的源代码!
  2. 利用高阶函数(返回函数名),没有修改被装饰函数的调用方式.
  3. 利用嵌套函数把装饰器封装成一个函数,借助语法糖@调用。
'''利用装饰器打印出函数的执行时间'''import timedef timmer(func):    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()        print("The func.__name__ running %s second" % (stop_time-start_time))    return wrapper

@timmer     #装饰器的语法糖,这句等价于test1 = timmer(test1)def test1():
    time.sleep(1)
@timmerdef test2(): #装饰器的语法糖,这句等价于test2 = timmer(test2),
    time.sleep(2)

test1()  #原函数的源代码和调用方式均没有改变test2()


上面的原函数及装饰器均没有参数,带参数的装饰器:

'''利用装饰器打印出函数的执行时间'''import timedef timmer(func):    def wrapper(*args,**kwargs):   #被装饰函数的参数是传递给wrapper的,因此wrapper函数需要能接收参数
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()        print("The %s running %s second" % (func.__name__,stop_time-start_time))    return wrapper

@timmer     #装饰器的语法糖,这句等价于test = timmer(test1)def test1(name):    print (name.center(50,"-"))
    time.sleep(1)
@timmerdef test2(name): #装饰器的语法糖,这句等价于test = timmer(test2),
    print(name.center(50,"-"))
    time.sleep(2)

test1("LFY")  #原函数的源代码和调用方式均没有改变test2("WXZ")


有一个需求,对于不同的被装饰函数,根据传入的参数不同,添加不同的功能!

两种方法:

  • 再写一个装饰器(不推荐)。
  • 第二种方法根据参数的不同,选择不同的装饰器。

对于test1函数和test2函数上面的装饰器,都添加显示执行时间的功能;现在有如下需求:对于test1不变,仍然添加函数执行时间的功能,对于test2函数添加打印出函数的开始执行时间和结束的时间。

# *-*coding:utf-8 *-*# Auth: wangxzimport  timedef timmer(type):   #就是在装饰器的外层在嵌套一个函数
    def out_wrapper(func):        def wrapper(*args, **kwargs):            if type == "one":
                start_time = time.time()
                func(*args, **kwargs)
                stop_time = time.time()                print("The %s running %s second" % (func.__name__, stop_time - start_time))            elif type == "two":                print("The %s runging start at %s" % (func.__name__, time.time()))
                func(*args, **kwargs)                print("The %s runging staop at %s" % (func.__name__, time.time()))        return wrapper    return out_wrapper

@timmer("one")  ##注意的是这个实参,传递给了那个形参def test1(name):    print (name.center(50,"-"))
    time.sleep(1)

@timmer("two") #def test2(name): #装饰器的语法糖,这句等价于test = timmer(test2),
    print(name.center(50,"-"))
    time.sleep(2)

test1("WXZ")   #根据传递的语法糖的参数不同,选择不同的装饰器test2("LFY")     #

这段函数代码的执行结果如下:

#代码执行的结果如下:-----------------------WXZ------------------------The test1 running 1.0000572204589844 second
The test2 runging start at 1524373351.098816
-----------------------LFY------------------------The test2 runging staop at 1524373353.0989301Process finished with exit code 0

需要注意的是:

    如果被装饰的函数有return返回值,那么在装饰器的wrapper()函数中,也需要使用return语句返回函数的结果。

  

---恢复内容结束---

上一篇:C#进阶语法复习——泛型


下一篇:如何在cmd命令行窗口测试MySQL数据的innodb存储引擎行锁实现方式