Python中的属性拦截与动态属性访问:`__getattr__`、`__getattribute__`与`__setattr__`
字数 635 2025-11-06 22:53:29
Python中的属性拦截与动态属性访问:__getattr__、__getattribute__与__setattr__
在Python中,属性拦截是指在访问、设置或删除对象属性时,通过特殊方法进行自定义处理的能力。这三大核心方法构成了Python动态属性访问的基石。
1. __getattr__与__getattribute__的区别
__getattr__:仅在正常属性查找失败时触发。当访问不存在的属性时,Python会调用此方法作为后备机制。__getattribute__:每次属性访问都会触发,无论属性是否存在。它完全接管了属性查找过程。
示例演示:
class DynamicClass:
def __init__(self):
self.existing_attr = "我是已存在的属性"
def __getattr__(self, name):
print(f"__getattr__被触发,访问不存在的属性: {name}")
return f"动态创建的属性: {name}"
def __getattribute__(self, name):
print(f"__getattribute__被触发,访问属性: {name}")
return super().__getattribute__(name) # 必须调用父类方法避免递归
obj = DynamicClass()
print(obj.existing_attr) # 触发__getattribute__
print(obj.non_existing) # 先触发__getattribute__,再触发__getattr__
输出结果:
__getattribute__被触发,访问属性: existing_attr
我是已存在的属性
__getattribute__被触发,访问属性: non_existing
__getattr__被触发,访问不存在的属性: non_existing
动态创建的属性: non_existing
2. __setattr__的工作原理
__setattr__在每次设置属性时触发,包括在__init__中的初始化赋值。需要特别注意避免递归调用:
class SafeSetAttr:
def __init__(self):
self._data = {} # 使用特殊名称避免递归
self.value = 10 # 这会触发__setattr__
def __setattr__(self, name, value):
if name == "_data": # 允许_data初始化
super().__setattr__(name, value)
else:
print(f"设置属性 {name} = {value}")
self._data[name] = value # 存储到内部字典
obj = SafeSetAttr()
obj.new_attr = "hello" # 触发__setattr__
print(obj._data) # 查看存储的数据
4. 实际应用场景:动态代理模式
结合使用这些方法可以实现强大的动态代理功能:
class AttributeProxy:
"""将属性访问转发到另一个对象"""
def __init__(self, target):
super().__setattr__('_target', target) # 绕过__setattr__
def __getattr__(self, name):
return getattr(self._target, name) # 转发到目标对象
def __setattr__(self, name, value):
setattr(self._target, name, value)
class RealClass:
def __init__(self):
self.x = 100
real = RealClass()
proxy = AttributeProxy(real)
print(proxy.x) # 通过代理访问属性
proxy.y = 200 # 通过代理设置属性
5. 注意事项与最佳实践
- 在
__getattribute__和__setattr__中必须使用super()来避免递归 __getattr__应处理不存在的属性,对于已知属性应抛出AttributeError- 性能考虑:
__getattribute__会影响所有属性访问,需谨慎使用
通过这三个特殊方法的组合使用,可以实现属性验证、延迟加载、动态创建等高级功能,充分体现Python的动态特性。