装饰器是Python中的一个高级功能,它可以用来扩展或修改一个函数或方法的功能,而不需要修改其原始代码。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数对象。
装饰器通常用于添加与函数功能无关的额外功能,如日志记录、性能测试、事务处理、缓存和权限校验等。通过使用装饰器,我们可以将与函数功能无关的代码抽离出来,并继续重用。
使用装饰器可以让我们动态地添加功能到函数或方法中,而不需要修改其原始代码。这种动态添加功能的方式被称为“装饰器”(Decorator),提供一种简洁而优雅的方式来修改、扩展或包装函数,使代码更具可读性和可维护性。
1.写一个简单的装饰器:在这个例子中,我们定义了一个名为count_time的装饰器函数。这个函数接受一个函数作为参数,并返回一个新的函数对象wrapper。在wrapper函数中,记录函数的运行的时间 。
接下来,我们使用装饰器来修饰一个名为my_python的函数。我们通过在函数定义之前加上@count_time来应用装饰器。当调用my_python时,实际上是调用了被装饰器返回的wrapper函数。
import timedef count_time(func):def wrapper():t1 = time.time()func()t2 = time.time()# 保留5位小数print('运行时间为:{:.5} s'.format(t2 - t1))return wrapper# 用语法糖@+函数名,就可以直接调用该函数了
@count_time
def my_python():time.sleep(1)print('我的Python教程,微信公众号:wdPython')my_python()# 我的Python教程,微信公众号:wdPython
# 运行时间为:1.0008 s
2.带有返回值的函数,如何写装饰器:下面代码中执行my_python函数后,有一个常量返回值888888,那么你在wrapper函数里面,也要加进去返回值,这样才能打印出my_python函数的返回值。
import timedef count_time(func):def wrapper():t1 = time.time()result = func()t2 = time.time()# 保留5位小数print('运行时间为:{:.5} s'.format(t2 - t1))return resultreturn wrapper# 用语法糖@+函数名,就可以直接调用该函数了
@count_time
def my_python():time.sleep(1)print('我的Python教程,微信公众号:wdPython')return 888888constant = my_python()
print(constant)
输出内容 :
我的Python教程,微信公众号:wdPython
运行时间为:1.0003 s
88888
**3.函数带参数,如何写装饰器:**首先在my_python函数中,定义一个times参数,表示打印我的Python教程的次数。然后在wrapper函数里面,把*ags参数传进来。ags用于接收一个,可变数量的参数列表,可以一个,可以n个。
import timedef count_time(func):def wrapper(*ags):t1 = time.time()result = func(*ags)t2 = time.time()# 保留5位小数print('运行时间为:{:.5} s'.format(t2 - t1))return resultreturn wrapper# 用语法糖@+函数名,就可以直接调用该函数了
@count_time
def my_python(times):time.sleep(1)print('我的Python教程,微信公众号:wdPython\n'*times)return 888888constant = my_python(3)
print(constant)
输出内容:
我的Python教程,微信公众号:wdPython
我的Python教程,微信公众号:wdPython
我的Python教程,微信公众号:wdPython运行时间为:1.0007 s
888888
2.装饰器带参数:当我们的被装饰的函数是带参数的,此时要怎么写装饰器呢?…
import time
def my_decorator(name):def count_time(func):def wrapper(*args, **kwargs):t1 = time.time()func(*args, **kwargs)t2 = time.time()print(f'[{name}]执行时间为:', t2 - t1)return wrapperreturn count_time@my_decorator(name='李白')
def libai():time.sleep(1)print('我是李白')@my_decorator(name='杜甫')
def dufu():time.sleep(1)print('我是杜甫')libai()
dufu()
输出内容:
我是李白
[李白]执行时间为:1.0057024955749512
我是杜甫
[杜甫]执行时间为: 1.002488374710083
4.类装饰器的用法:在装饰器内部,我们定义了__init__和__call__方法,它们分别在创建类实例和调用类实例时被调用。
import timeclass my_decorator:def __init__(self, func):self.func = funcprint("执行类的__init__方法")def __call__(self, *args, **kwargs):# 添加装饰器的功能print('进入__call__函数')t1 = time.time()self.func(*args, **kwargs)t2 = time.time()print('运行时间为:{:.5} s'.format(t2 - t1))@my_decorator
def my_python():print('我的Python教程,微信公众号:wdPython')time.sleep(1.02)my_python()
输出内容
执行类的__init__方法
进入__call__函数
我的Python教程,微信公众号:wdPython
运行时间为:1.0219 s
5.类装饰器的传参
class my_decorator:def __init__(self, arg1, arg2): # init()方法里面的参数都是装饰器的参数print('执行类Decorator的__init__()方法')self.arg1 = arg1self.arg2 = arg2def __call__(self, func): # 因为装饰器带了参数,所以接收传入函数变量的位置是这里print('执行类Decorator的__call__()方法')def baiyu_warp(*args): # 这里装饰器的函数名字可以随便命名,只要跟return的函数名相同即可print('执行wrap()')print('装饰器参数:', self.arg1, self.arg2)print('执行' + func.__name__ + '()')func(*args)print(func.__name__ + '()执行完毕')return baiyu_warp@my_decorator('李白', '杜甫')
def demo(a, b, c):print('函数的参数:', a, b, c)demo(10, 20, 30)
输出内容:
执行类Decorator的__init__()方法
执行类Decorator的__call__()方法
执行wrap()
装饰器参数: 李白 杜甫
执行demo()
函数的参数: 10 20 30
demo()执行完毕
完毕!!感谢您的收看
----------★★历史博文集合★★----------
我的零基础Python教程,Python入门篇 进阶篇 视频教程 Py安装py项目 Python模块 Python爬虫 Json Xpath 正则表达式 Selenium Etree CssGui程序开发 Tkinter Pyqt5 列表元组字典数据可视化 matplotlib 词云图 Pyecharts 海龟画图 Pandas Bug处理 电脑小知识office自动化办公 编程工具