装饰器概述
装饰器允许在不修改原有函数代码的情况下给函数增加新的功能
装饰器本质上是一个函数,它可以接收一个函数作为参数并返回一个新的函数。这个新函数是对原函数的一种包装或增强,可以在不改变原函数代码的前提下,增加额外的功能。
def mydecorator(func):
def wrapper(*args, **kwargs):
print("Before calling the function")
result = func(*args, **kwargs)
print("After calling the function")
return result+5
return wrapper
@mydecorator
def my_function(x, y):
return x+y
print(my_function(1, 2))
使用装饰器的步骤
定义装饰器:首先定义一个装饰器函数,该函数接收一个函数作为参数。
定义包装函数:在装饰器函数内部,定义一个包装函数(wrapper),这个包装函数会调用原函数,并可以在调用前后添加额外的逻辑。
返回包装函数:装饰器函数返回这个包装函数。
使用@语法:在需要被装饰的函数定义前使用@符号加上装饰器名称,这样Python解释器会自动将这个函数作为参数传递给装饰器,并将返回的新函数(包装函数)赋值给原函数名。
注意:带参数的装饰器,当被装饰的函数需要参数时,装饰器中的包装函数(wrapper)也需要能够接收这些参数。这通常通过*args和**kwargs实现。
装饰器带参数
def mydecorator2(count):
def mydecorator(func):
def wrapper(*args, **kwargs):
result = 0
for i in range(count):
print("Before calling the function")
result += func(*args, **kwargs)
result += 1
print("After calling the function")
return result
return wrapper
return mydecorator
@mydecorator2(3)
def my_function(x, y):
return x+y
print(my_function(1, 2))
使用functools.wraps保留原函数信息
在使用装饰器时,原函数的元信息(如函数名、文档字符串等)会被包装函数所替代。为了保留这些信息,可以使用functools.wraps装饰器。
from functools import wraps
def mydecorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""function2"""
print("Before calling the function")
result = func(*args, **kwargs)
print("After calling the function")
return result+5
return wrapper
@mydecorator
def my_function(x, y):
"""function1"""
return x+y
print(my_function(1, 2))
print(my_function.__doc__)
args和kwargs
def demo(*args, **kwargs):
print(args)
print(kwargs)
gl_nums = (1, 2, 3)
gl_dict = {"name":"小明", "age":18}
demo(gl_nums, gl_dict) # 把两个变量都传给了*args
demo(*gl_nums, **gl_dict) # 拆包方式
# 输出
((1, 2, 3), {'name': '小明', 'age': 18})
{}
(1, 2, 3)
{'name': '小明', 'age': 18}