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 time

def 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)
@timmer
def test2(): #装饰器的语法糖,这句等价于test2 = timmer(test2),
    time.sleep(2)

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


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

'''
利用装饰器打印出函数的执行时间
'''
import time

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

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


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

两种方法:

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

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

# *-*coding:utf-8 *-*
# Auth: wangxz
import  time

def 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.0989301

Process finished with exit code 0

需要注意的是:

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

 

 

 

 

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

posted @ 2018-04-22 13:12  夜间独行的浪子  阅读(192)  评论(0编辑  收藏  举报