Python


331 浏览 3 years, 11 months

10.2 装饰器使用的形式

版权声明: 转载请注明出处 http://www.codingsoho.com/

装饰器使用的形式

  • 嵌套使用装饰器
  • 不带参数的装饰器
  • 带参数的装饰器

嵌套使用装饰器

@decor1
@decor2
@decor3
def hello(name):
    print(name)

注意装饰顺序, 距离被装饰函数越近的越先调用, 效果等同于

hello = decor1(decor2(decor3(hello)))

嵌套使用装饰器的例子:

def decor1(f):
    def wrapper(name):
        print("Hello from decor1")
        f(name)
    return wrapper

def decor2(f):
    def wrapper(name):
        print("Hello from decor2")
        f(name)
    return wrapper

def decor3(f):
    def wrapper(name):
        print("Hello from decor3")
        f(name)
    return wrapper

@decor1
@decor2
@decor3
def hello(name):
    print("Hello,", name)

hello(Zhang San)

不带参数的装饰器

我们前面举得例子基本是不带参数的

带参数与不带参数的装饰器比较

  • 不带参数
@hello_decor
def hello(name):
    print("How are you? {}".format(name))

相当于

def hello(name):
    print("How are you? {}".format(name))
hello = hello_decor(hello)
  • 带参数
@repeat_hello_decor(3)
def hello(name):
    print("How are you? {}".format(name))

相当于

def hello(name):
print("How are you? {}".format(name))
    hello = repeat_hello_decor(3)(hello)

带参数的装饰器

def repeat_hello_decor(number):
    def wrapper(f):
        def proxy(name):
            print("Inside proxy")
            for x in range(number):
                f(name)
        return proxy
    return wrapper
@decor(3)
def hello(name):
print("Hello", name)

参数number控制hello函数执行的次数

注意:带参数的装饰器在装饰时是带扩招的,不带参数的则没有括号

练习

实现一个装饰器,其对下面给定函数的执行时间进行统计,统计其执行了多少秒。运行时间打印出来即可。

def func():
    print("Inside func")
    print("Running ....")
    for i in range(5):
        print("Counting {}".format(i))
        time.sleep(0.5)
    print("Exit func")

给这个装饰器增加一个参数,用来指定func函数运行的次数。算出平均执行时间。把运行次数和平均运行时间打印出来。

解答
def wrapper(func):
    def cal():
        t1 = time.time()
        func()
        delta = time.time()-t1
        print("time consuming {}".format(delta))
    return cal

@wrapper
def func():
    print("Inside func")
    print("Running ....")
    for i in range(5):
        print("Counting {}".format(i))
        time.sleep(0.5)
    print("Exit func")

import time
func()

执行结果

Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.501143217086792

如果添加执行次数参数,代码修改如下

def wrapper_param(times):    
    def wrapper(func):
        def cal():
            consumed = 0
            for i in range(times):
                t1 = time.time()
                func()
                delta = time.time()-t1
                consumed = consumed + delta
                print("time consuming {}".format(delta))
            ave_consumed = consumed / times
            print("run {} times, average time consuming {}".format(times, ave_consumed))
        return cal
    return wrapper

@wrapper_param(10)
def func():
    print("Inside func")
    print("Running ....")
    for i in range(5):
        print("Counting {}".format(i))
        time.sleep(0.5)
    print("Exit func")

import time
func()    

执行结果如下

Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.501143217086792
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500142812728882
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.501142978668213
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500143051147461
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500142812728882
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.50014328956604
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500142812728882
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.506143569946289
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500142812728882
Inside func
Running ....
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Exit func
time consuming 2.500143051147461
run 10 times, average time consuming 2.5009430408477784