装饰器是Python中的一个高级功能,它可以用来扩展或修改一个函数或方法的功能,而不需要修改其原始代码。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数对象。
装饰器通常用于添加与函数功能无关的额外功能,如日志记录、性能测试、事务处理、缓存和权限校验等。通过使用装饰器,我们可以将与函数功能无关的代码抽离出来,并继续重用。
使用装饰器可以让我们动态地添加功能到函数或方法中,而不需要修改其原始代码。这种动态添加功能的方式被称为“装饰器”(Decorator),提供一种简洁而优雅的方式来修改、扩展或包装函数,使代码更具可读性和可维护性。
1.写一个简单的装饰器:在这个例子中,我们定义了一个名为count_time的装饰器函数。这个函数接受一个函数作为参数,并返回一个新的函数对象wrapper。在wrapper函数中,记录函数的运行的时间 。
接下来,我们使用装饰器来修饰一个名为my_python的函数。我们通过在函数定义之前加上@count_time来应用装饰器。当调用my_python时,实际上是调用了被装饰器返回的wrapper函数。
import time
def 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 time
def count_time(func):
def wrapper():
t1 = time.time()
result = func()
t2 = time.time()
# 保留5位小数
print('运行时间为:{:.5} s'.format(t2 - t1))
return result
return wrapper
# 用语法糖@+函数名,就可以直接调用该函数了
@count_time
def my_python():
time.sleep(1)
print('我的Python教程,微信公众号:wdPython')
return 888888
constant = my_python()
print(constant)
输出内容 :
我的Python教程,微信公众号:wdPython
运行时间为:1.0003 s
88888
**3.函数带参数,如何写装饰器:**首先在my_python函数中,定义一个times参数,表示打印我的Python教程的次数。然后在wrapper函数里面,把*ags参数传进来。ags用于接收一个,可变数量的参数列表,可以一个,可以n个。
import time
def count_time(func):
def wrapper(*ags):
t1 = time.time()
result = func(*ags)
t2 = time.time()
# 保留5位小数
print('运行时间为:{:.5} s'.format(t2 - t1))
return result
return wrapper
# 用语法糖@+函数名,就可以直接调用该函数了
@count_time
def my_python(times):
time.sleep(1)
print('我的Python教程,微信公众号:wdPython\n'*times)
return 888888
constant = 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 wrapper
return 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 time
class my_decorator:
def __init__(self, func):
self.func = func
print("执行类的__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 = arg1
self.arg2 = arg2
def __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自动化办公 编程工具