装饰器三种写法之带参数的装饰器

装饰器是AOP编程思想,给主体函数增加功能,又不让代码入侵到主体函数中,实现高内聚,低耦合。

如果装饰功能部分代码也需要参数的话,可以在原来的两层函数外面再加一层,专门用来接收参数。

举例:给一个函数增加日志,这里的日志就简化为一个log.txt里面写入一句话。

写法1:装饰器函数

def decoLog(filename):
    def log(func):
        def wrapper(*args, **kwargs):
            log = '函数{}日志'.format(func.__name__)
            with open(filename, 'a', encoding='utf-8') as f:
                f.write(log + '\n')
                func(*args, **kwargs)
        return wrapper
    return log

@decoLog('log1.txt')
def tony(num):
    print(tony.__name__+str(num))

tony(1)

执行结果:

控制台:

wrapper1

log1.txt:

函数tony日志

写法2:类装饰器

__call__方法

class DecoLog:
    def __init__(self,filename):
        self.filename = filename

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            log = '函数{}日志'.format(func.__name__)
            with open(self.filename, 'a', encoding='utf-8') as f:
                f.write(log + '\n')
                func(*args, **kwargs)
        return wrapper

@DecoLog('log2.txt')
def tony(num):
    print(tony.__name__+str(num))

tony(2)

执行结果:

控制台:

wrapper2

log2.txt:

函数tony日志

写法3:类装饰器

生成类的对象,对象调用方法

class DecoLog():
    def __init__(self,filename):
        self.filename = filename

    def log(self,func):
        def wrapper(*args, **kwargs):
            log = f'函数{func.__name__}日志'
            with open(self.filename, 'a', encoding='utf8') as f:
                f.write(log +'\n')
                func(*args, **kwargs)
        return wrapper

decoLog = DecoLog('log3.txt')

@decoLog.log
def tony(num):
    print(tony.__name__+str(num))

tony(3)

执行结果:

控制台:

wrapper3

log3.txt:

函数tony日志

总结:以上就是3中装饰器的实现,都是使tony函数变成了wrapper函数。@写法只是语法糖。

发现一个问题,日志文件中打印的是tony,而控制台是wrapper。这是因为执行tony函数时tony函数已经变成wrapper函数,tony.__name__获取的名字是wrapper函数名。python中为了解决这个问题,内置了wraps,装饰在最终取代原函数的函数上面。

from functools import wraps

def decoLog(filename):
    def log(func):
        @wraps(func)   //加在最终返回的取代tony的函数上
        def wrapper(*args, **kwargs):
            log = '函数{}日志'.format(func.__name__)
            with open(filename, 'a', encoding='utf-8') as f:
                f.write(log + '\n')
                func(*args, **kwargs)
        return wrapper
    return log

@decoLog('log1.txt')
def tony(num):
    print(tony.__name__+str(num))

tony(1)

控制台打印结果:

tony1

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值