Python 装饰器
Python 装饰器(decorator)是一种用于扩展或修改现有函数功能的函数。它可以在不改变被装饰函数的源代码的情况下,为函数添加额外的行为。
装饰器的本质是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新函数通常会在内部调用被装饰的函数,并在调用前后添加一些额外的逻辑。
以下是一个简单的装饰器示例:
import timedef timer(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()execution_time = (end_time - start_time) * 1000print(f"time is {execution_time} ms")return resultreturn wrapper@timer
def my_function(a, b):print(f"result is {a + b}")time.sleep(1) my_function(3, 4)
在上述示例中,timer 就是一个装饰器函数。它定义了一个内部函数 wrapper,该函数接受任意数量的位置参数 *args
和关键字参数 **kwargs
。
在 wrapper 函数内部,首先记录开始时间,然后调用被装饰的函数 func(*args, **kwargs)
,并获取其返回结果。接着计算函数的执行时间,打印出来,最后返回函数的执行结果。
使用 @timer 来装饰 my_function 函数,就相当于执行了 my_function = timer(my_function)
,将 my_function 替换为经过装饰后的 wrapper 函数。这样,当调用 my_function(3, 4)
时,实际上是在调用 wrapper(3, 4)
,从而实现了对函数执行时间的计算和打印,同时仍然能够得到原函数的返回结果。
装饰器的主要优点包括:
- 遵循开放封闭原则:可以在不修改原有函数代码的基础上进行功能扩展。
- 提高代码的复用性:可以将相同的装饰逻辑应用于多个函数。
- 使代码更简洁、清晰:将额外的功能从函数本身的业务逻辑中分离出来。
装饰器还可以带有参数、用于类的方法等,以下是一些扩展的示例:
1.带参数的装饰器:
def deco_factory(argument):def deco(func):def wrapper(*args, **kwargs):# 使用参数进行一些额外的操作print(f"Decorator argument: {argument}")result = func(*args, **kwargs)return resultreturn wrapperreturn deco@deco_factory("my_argument")
def my_function(a, b):print(f"result is {a + b}")my_function(3, 4)
2.类装饰器:
类也可以用作装饰器,通过实现 __call__
方法来模拟函数的行为。
class MyDecorator:def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print("Before function execution")result = self.func(*args, **kwargs)print("After function execution")return result@MyDecorator
def my_function(a, b):print(f"result is {a + b}")my_function(3, 4)
3.多个装饰器的使用:
一个函数可以被多个装饰器装饰,装饰器的应用顺序与声明顺序相反。
def decorator1(func):def wrapper(*args, **kwargs):print("Decorator 1 before")result = func(*args, **kwargs)print("Decorator 1 after")return resultreturn wrapperdef decorator2(func):def wrapper(*args, **kwargs):print("Decorator 2 before")result = func(*args, **kwargs)print("Decorator 2 after")return resultreturn wrapper@decorator1
@decorator2
def my_function(a, b):print(f"result is {a + b}")my_function(3, 4)
在这个例子中,调用 my_function(3, 4)
时,输出的顺序是 “Decorator 1 before”、“Decorator 2 before”、“result is 7”、“Decorator 2 after”、“Decorator 1 after”。
4.用装饰器来添加函数的日志记录功能
import logging# 定义装饰器函数
def add_logging(func):def wrapper(*args, **kwargs):logging.info(f"Entering function: {func.__name__}") # 记录进入函数的信息result = func(*args, **kwargs)logging.info(f"Exiting function: {func.__name__}, result: {result}") # 记录函数退出及结果return resultreturn wrapper# 配置日志记录
logging.basicConfig(level=logging.INFO)# 示例函数
@add_logging
def add_numbers(a, b):return a + badd_numbers(2, 3)
在上述代码中,我们定义了一个名为 add_logging 的装饰器函数。它内部的 wrapper 函数负责记录函数进入和退出的日志信息以及函数的返回结果。
Python 内置了一些装饰器,例如 staticmethod、classmethod 和 property。staticmethod 用于定义类静态方法,它没有 self 参数,可以在不创建类实例的情况下调用;classmethod 的第一个参数不是 self 而是 cls,表示当前类;property 用于定义属性,可以通过类实例直接访问。
装饰器是 Python 中非常强大和灵活的特性,能够帮助开发者更优雅地组织和扩展代码的功能。通过使用装饰器,可以使代码更具可读性、可维护性和可扩展性。要深入理解和掌握装饰器,需要在实际编程中不断实践和体会。