Python类装饰器

python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原“”函数的函数

  • (1).只要有被类装饰器装饰的对象,类装饰器的 init 函数就会执行(不需要调用)
  • (2).被类装饰器装饰的函数不论被调用几次,init 函数只会执行一次,并且它的执行是被装饰函数声明装饰时就自动执行,不需要手动调用
  • (3).当被装饰函数存在参数时,从__call__ 函数传进参数(不必须 *args,但这是一种规范 def __call__(self,*args,**kwargs)) *args是指元组,**kwargs是指字典,可以接受任何形式的参数

注意:

  • (1).类装饰器有类装饰器的参数,函数(被装饰器修饰的函数)有函数的参数,不可混淆

  • (2).类装饰器的参数从__init__函数中传,函数的参数从 __call__函数中传

1、不带参数的类装饰器
from datetime import datetime
import time


# 不带参数的类装饰器
class MyLog():
    def __init__(self, func):
        print("初始化  {}".format(datetime.now()))
        time.sleep(1)
        self.func = func

    def __call__(self, *args, **kwargs):
        print("装饰函数  {}".format(datetime.now()))
        time.sleep(1)
        return self.func(*args, **kwargs)

@MyLog
def show(name):
    print("show function start  {}".format(datetime.now()))
    print(name)
    time.sleep(1)
    return "success"


if __name__ == '__main__':
    result = show("tom")
    print(result)

# output
'''
初始化  2019-06-12 23:33:25.696782
装饰函数  2019-06-12 23:33:26.704644
show function start  2019-06-12 23:33:27.705616
tom
success
'''
2、带参数的类装饰器
from datetime import datetime
import time

# 带参数的类装饰器
class MyLog():
    def __init__(self, name, age):
        print("初始化  {}".format(datetime.now()))
        self.name = name
        self.age = age
        time.sleep(1)
        print("类装饰器初始化内容  {}: {}  {}".format(self.name, self.age, datetime.now()))
        time.sleep(1)

    def __call__(self, func):
        print("进入装饰函数  {}".format(datetime.now()))
        time.sleep(1)

        def wrapper(*args, **kwargs):
            print("开始装饰函数  {}".format(datetime.now()))
            time.sleep(1)
            return func(*args, **kwargs)
        return wrapper


@MyLog("jack", 22)
def show(name, age):
    print("show function start  {}".format(datetime.now()))
    print("{} :  {}  {}".format(name, age, datetime.now()))
    time.sleep(1)
    return "success"

if __name__ == '__main__':
    result = show("rose", 20)
    print(result)

# output
'''
初始化  2019-06-12 23:35:24.826855
类装饰器初始化内容  jack: 22  2019-06-12 23:35:25.827581
进入装饰函数  2019-06-12 23:35:26.827861
开始装饰函数  2019-06-12 23:35:27.828399
show function start  2019-06-12 23:35:28.828962
rose :  20  2019-06-12 23:35:28.828962
success
'''
3、处理被装饰函数的参数
from datetime import datetime
import time
from functools import wraps


# 带参数的类装饰器
class MyLog():
    def __init__(self, name, age):
        print("初始化  {}".format(datetime.now()))
        self.name = name
        self.age = age
        time.sleep(1)
        print("类装饰器初始化内容  {}: {}  {}".format(self.name, self.age, datetime.now()))
        time.sleep(1)

    def __call__(self, func):
        print("进入装饰函数  {}".format(datetime.now()))
        time.sleep(1)
		
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("开始装饰函数  {}".format(datetime.now()))

            # 需要先将参数元组形式转换成列表,进行操作
            old_args = list(args)
            new_args = []
            
            # kwargs 参数是字典的形式,直接可以键值对复制修改

            for index, var in enumerate(old_args):
                if var == "rose":
                    var = "mary"
                new_args.append(var)

            time.sleep(1)
            return func(*tuple(new_args), **kwargs)
        return wrapper

@MyLog("jack", 22)
def show(name, age):
    print("show function start  {}".format(datetime.now()))
    print("{} :  {}  {}".format(name, age, datetime.now()))
    time.sleep(1)
    return "success"

if __name__ == '__main__':
    result = show("rose", 20)
    print(result)

# output
# 我们可以看到原函数传参名字 rose 被修改成了mary
# 年龄的参数我们并没有修改,不会影响到年龄参数
'''
初始化  2019-06-12 23:47:32.545398
类装饰器初始化内容  jack: 22  2019-06-12 23:47:33.545863
进入装饰函数  2019-06-12 23:47:34.546187
开始装饰函数  2019-06-12 23:47:35.546515
show function start  2019-06-12 23:47:36.546834
mary :  20  2019-06-12 23:47:36.546834
success
'''
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值