python装饰器

1、简介

功能:在不改变函数代码的基础上,添加额外的功能,比如计时

2、装饰器应用

2.1 无参数函数的装饰器

计算一个现有函数的运行时间,其中myfunc() 没有参数输入:

import time
from functools import wraps

def display_time(func):
    # @wraps(func)
    def wrap_func():
        'this is wrap_func'
        t1 = time.time()
        func()
        t2 = time.time()
        print("Total time: {:.4} s".format(t2-t1))
    return wrap_func
    
@display_time
def myfunc():
    'this is myfunc'
    print('myfunc is runing')
    
myfunc()
print('function name : {}'.format(myfunc.__name__))
print('function message: {}'.format(myfunc.__doc__))

运行结果:

myfunc is runing
Total time: 7.892e-05 s
function name : wrap_func
function message: this is wrap_func

注:myfunc()这个函数使用了装饰器,函数的__name__、__doc__被装饰器改变,函数的实际内存地址指向了wrap_func(),所以打印出来的myfunc.name、myfunc.__doc__为wrap_func()的函数名、注释。

解决方案就是引入内置的装饰器:funtools.wraps,代码如下:

import time
from functools import wraps

def display_time(func):
    @wraps(func)
    def wrap_func():
        'this is wrap_func'
        t1 = time.time()
        func()
        t2 = time.time()
        print("Total time: {:.4} s".format(t2-t1))
    return wrap_func

@display_time
def myfunc():
    'this is myfunc'
    print('myfunc is runing')

myfunc() 
print('function name : {}'.format(myfunc.__name__))
print('function message: {}'.format(myfunc.__doc__))

运行结果

myfunc is runing
Total time: 7.057e-05 s
function name : myfunc
function message: this is myfunc

2.2 带参数函数的装饰器

知识点:

  • *args 用来将参数打包成tuple给函数体调用
  • **kwargs 打包关键字参数成dict给函数体调用

实现如下:

import time
from functools import wraps

def display_time(func):
    @wraps(func)
    def wrap_func(*args, **kwargs):
        'this is wrap_func'
        t1 = time.time()
        res = func(*args, **kwargs)
        t2 = time.time()
        print("Total time: {:.4} s".format(t2-t1))
        return res
    return wrap_func

@display_time  
def myfunc(anum, *args, **kwargs):  #def myfunc(anum, atuple, adict):   
    'this is myfunc'
    print('myfunc is runing')

    print('num: {}'.format(anum))
    print('tuple: {}'.format(args))
    print('adict: {}'.format(kwargs))
    
    return args

t = myfunc(3, 4, 5, 6, a=1, b=2, c=3)   #,, a=1 b=2, c=3
print(t)

运行结果:

myfunc is runing
num: 3
tuple: (4, 5, 6)
adict: {‘a’: 1, ‘b’: 2, ‘c’: 3}
Total time: 0.0002067 s
(4, 5, 6)

2.3 带参数的装饰器

一个日志装饰器

from functools import wraps
 
def logit(logfile='out.log'):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打开logfile,并写入内容
            with open(logfile, 'a') as opened_file:
                # 现在将日志打到指定的logfile
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)
        return wrapped_function
    return logging_decorator
 
@logit()
def myfunc1():
    pass
 
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
 
@logit(logfile='func2.log')
def myfunc2():
    pass
 
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
装饰器类

待理解,具体可见 参考文献5

参考文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值