装饰器的实现,类装饰器

一、装饰器的目的

我们需要遵守开放封闭原则。

  开放封闭原则:程序上线以后就应该对修改封闭,对扩展开放

  修改封闭:不能修改功能性函数的源代码

  不能修改功能性函数的调用方式

  扩展开放:可以为原有的功能添加新功能

 

二、装饰器的逐步实现

首先,我们定义一个函数

import time, random
def msg():
  print('I have something to tell you, please wait a moment.')
  time.sleep(random.randint(1, 5))
 print('I like you.')
msg()

该函数会随机休眠1-5秒钟。

现在,我们想要给该函数增加一个计时的功能,看看函数具体运行了多久。

import time, random
def msg():
    print('I have something to tell you, please wait a moment.')
    time.sleep(random.randint(1, 5))
    print('I like you.')
start_time = time.time()
msg()
stop_time = time.time()
print('Run time is %s' % (stop_time - start_time))

并且如果要重复使用计时功能,就要写重复代码,所以我们想到了将计时功能封装成一个函数

def wrapper():
    start = time.time()
    msg()
    stop = time.time()
    print('Run time is %s' % (stop - start))
    wrapper()

我们将wrapper函数写死了,只能对内部调用的msg函数进行计时,使用闭包函数

def timmer(func):  
    def wrapper():  
        start = time.time()
        func()
        stop = time.time()
        print('Run time is %s' % (stop - start))
        return wrapper  # 将wrapper函数的内存地址作为返回值返回。
    msg = timmer(msg)  # 作为参数的msg是我们定义的msg函数的内存地址

# 作为变量名的msg是指向wrapper函数的内存地址
msg() 此时我们这样写看似在调用msg函数,但实际上是调用了wrapper函数
这样子我们就实现了偷梁换柱,在外观上没有更改msg函数的调用方式。

当传入的函数有参数或者有返回值时

def timmer(func):
    def wrapper(*args, **kwargs):
        strat_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        return res
    return wrapper

装饰器的使用方法:语法糖

import time, random
def timmer(func):
    def wrapper(*args, **kwargs):
        strat_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        return res
    return wrapper
@timmer
def msg():
    print('I have something to tell you, please wait a moment.')
    time.sleep(random.randint(1, 5))
    print('I like you.')
msg()

含参装饰器,含参装饰器是一个三层的闭包函数

import time
def timemer(partment):
    def func(func_1):
        def wrapper(*args,**wkargs):
            if partment=='task1':
                start = time.time()
                func_1(*args, **wkargs)
                stop = time.time()
                print("the task1 run time is :", stop - start)
            elif partment=='task2':
                start = time.time()
                func_1(*args, **wkargs)
                stop = time.time()
                print("the task2 run time is :", stop - start)
        return wrapper
    return func
@timemer(partment='task1')
def task1():
    time.sleep(2)
    print("in the task1")
@timemer(partment='task2')
def task2():
    time.sleep(2)
    print("in the task2")
task1()
task2()

类实现的含参装饰器

 
 
from functools import wraps
class decorate:
    def __init__(self, name):
        self.name = name    # 装饰器的参数
def __call__(self, func): @wraps(func) def deco(*args, **kwargs): if self.name == 'Admin': passelif self.name == 'Student': passelif self.name == 'Teacher': passreturn func(*args, **kwargs) return deco

@decarate('Admin')

猜你喜欢

转载自www.cnblogs.com/wang-kai-1994/p/10222069.html