装饰器
大约 2 分钟PythonPython
装饰器
装饰器(Decorator)是Python中的一个重要特性,它可以在不修改函数代码的前提下,增强或改变函数的行为。
装饰器通常用于日志记录、性能测试、事务处理、缓存、权限校验等场景。
一、实现
装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。装饰器可以通过@
语法糖方便地应用于任何函数。
def my_decorator(func):
def wrapper():
print("Calling the function")
func()
print("Function has been called")
return wrapper
@my_decorator
def greet():
print("Greetings!")
greet()
Calling the function
Greetings!
Function has been called
可以看到通过装饰器,可以很方便的在函数前后加入一些通用的代码。
耗时统计
比如你想统计写的一些函数的耗时。如果没有装饰器就需要在每个函数的入口处记录开始时间,在函数返回前记录与开始时间的差值得到函数的耗时,但是当函数比较多的时候,需要给每个函数都做同样的修改。
而使用装饰器,只需要定义一个计算耗时的装饰器,在想要统计耗时的函数上加一个注解就可以实现,即简介,也避免了修改函数导致的bug。
import time
def timeit(func):
def wrapper():
start_time = time.time() # 记录开始时间
result = func()
end_time = time.time() # 记录结束时间
elapsed_time = end_time - start_time # 计算耗时
print(f"Function {func.__name__} took {elapsed_time:.4f} seconds to execute.")
return result
return wrapper
@timeit
def slow_function():
print("Method greet has been called.")
time.sleep(2)
print("Function has finished execution.")
slow_function()
Method greet has been called.
Function has finished execution.
Function slow_function took 2.0037 seconds to execute.
二、带参数的装饰器
有时,我们需要向装饰器传递额外的参数。为了实现这一点,我们可以编写一个返回装饰器的工厂函数。
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Bob")
Hello, Bob!
Hello, Bob!
Hello, Bob!
在这个例子中,repeat
函数是一个装饰器工厂,它生成一个装饰器,该装饰器使被装饰的函数重复执行n
次。
三、类的装饰器
装饰器不仅可以用于函数,也可以用于类。类装饰器可以用于修改类的行为或在类创建时进行一些初始化操作。
def method_decorator(method):
def wrapper(*args, **kwargs):
print(f"Calling method: {method.__name__}")
result = method(*args, **kwargs)
print(f"Method {method.__name__} has been called")
return result
return wrapper
# 遍历类中的每一个方法
def class_method_decorator(cls):
for attr_name, attr_value in cls.__dict__.items():
if callable(attr_value):
setattr(cls, attr_name, method_decorator(attr_value))
return cls
@class_method_decorator
class MyClass:
def greet(self, name):
print(f"Hello, {name}!")
instance = MyClass()
instance.greet("Charlie")
Calling method: greet
Hello, Charlie!
Method greet has been called
class_method_decorator
为MyClass
中的所有方法添加了日志打印功能。