Python中的类装饰器与函数装饰器的区别与实现原理
字数 532 2025-11-25 20:32:18
Python中的类装饰器与函数装饰器的区别与实现原理
题目描述
类装饰器和函数装饰器都是Python中用于修改或增强函数/类行为的工具,但它们在实现机制、应用场景和内部原理上存在重要差异。这个知识点考察你对装饰器本质的理解,以及如何根据需求选择适当的装饰器类型。
基本概念回顾
- 函数装饰器:接收函数作为参数,返回一个新函数的可调用对象
- 类装饰器:接收类作为参数,返回修改后的类或新类的可调用对象
函数装饰器的实现原理
def simple_decorator(func):
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@simple_decorator
def say_hello():
print("Hello!")
# 等价于:say_hello = simple_decorator(say_hello)
类装饰器的两种实现方式
方式一:返回修改后的原类
def add_method(cls):
"""类装饰器:给类添加新方法"""
def new_method(self):
return f"这是新增的方法,实例属性: {getattr(self, 'name', '无')}"
cls.get_info = new_method # 直接修改原类
return cls # 返回原类引用
@add_method
class Person:
def __init__(self, name):
self.name = name
person = Person("Alice")
print(person.get_info()) # 输出:这是新增的方法,实例属性: Alice
方式二:返回新类(继承方式)
def logged(cls):
"""类装饰器:创建继承原类的新类,添加日志功能"""
class NewClass(cls):
def __init__(self, *args, **kwargs):
print(f"创建 {cls.__name__} 实例")
super().__init__(*args, **kwargs)
NewClass.__name__ = f"Logged{cls.__name__}"
return NewClass
@logged
class Calculator:
def add(self, a, b):
return a + b
calc = Calculator() # 输出:创建 Calculator 实例
print(calc.add(2, 3)) # 输出:5
print(type(calc)) # 输出:<class '__main__.LoggedCalculator'>
带参数的类装饰器
def add_attributes(**kwargs):
"""带参数的类装饰器工厂函数"""
def decorator(cls):
for attr_name, attr_value in kwargs.items():
setattr(cls, attr_name, attr_value)
return cls
return decorator
@add_attributes(version="1.0", author="Python")
class MyClass:
pass
print(MyClass.version) # 输出:1.0
print(MyClass.author) # 输出:Python
类作为装饰器(可调用类)
class CountInstances:
"""类作为装饰器:统计类实例化次数"""
def __init__(self, cls):
self.cls = cls
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"创建第 {self.count} 个 {self.cls.__name__} 实例")
return self.cls(*args, **kwargs)
@CountInstances
class MyClass:
def __init__(self, name):
self.name = name
obj1 = MyClass("first") # 输出:创建第 1 个 MyClass 实例
obj2 = MyClass("second") # 输出:创建第 2 个 MyClass 实例
关键区别与选择标准
-
修改目标不同:
- 函数装饰器:修改函数行为
- 类装饰器:修改类定义或实例化过程
-
执行时机不同:
- 函数装饰器:在函数定义时执行一次
- 类装饰器:在类定义时执行一次
-
适用场景:
- 函数装饰器:日志、缓存、权限检查等函数级别增强
- 类装饰器:添加类方法、修改类属性、实现单例模式等类级别修改
实际应用示例:单例模式实现
def singleton(cls):
"""类装饰器实现单例模式"""
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class DatabaseConnection:
def __init__(self):
print("初始化数据库连接")
db1 = DatabaseConnection() # 输出:初始化数据库连接
db2 = DatabaseConnection() # 无输出(使用已创建的实例)
print(db1 is db2) # 输出:True
总结
类装饰器和函数装饰器虽然语法相似,但应用对象和内部机制完全不同。理解它们的区别有助于在适当场景选择正确的工具,类装饰器更适合对类结构进行元编程操作,而函数装饰器更适合增强函数行为。