Python属性动态管理
Python允许动态添加、修改、删除对象属性,这是元编程的基础能力。
dict 属性字典
Python
class Person:
def __init__(self, name):
self.name = name
p = Person("Alice")
# __dict__ 存储实例属性
print(p.__dict__) # {'name': 'Alice'}
# 直接修改 __dict__
p.__dict__['age'] = 30
print(p.age) # 30
# 动态添加属性
p.email = "alice@example.com"
print(p.__dict__) # {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}
Python
# 类的 __dict__
print(Person.__dict__.keys())
# 包含:__init__, __module__, __dict__, __weakref__ 等
# __dict__ 是 mappingproxy(只读视图)
print(type(Person.__dict__)) # <class 'mappingproxy'>
# Person.__dict__['new_attr'] = 1 # TypeError
setattr、getattr、delattr
Python
class Dynamic:
pass
obj = Dynamic()
# setattr(obj, name, value)
setattr(obj, 'x', 10)
setattr(obj, 'y', 20)
print(obj.x, obj.y) # 10 20
# getattr(obj, name, default)
print(getattr(obj, 'x')) # 10
print(getattr(obj, 'z', None)) # None(带默认值)
# getattr(obj, 'z') # AttributeError
# hasattr(obj, name)
print(hasattr(obj, 'x')) # True
print(hasattr(obj, 'z')) # False
# delattr(obj, name)
delattr(obj, 'x')
print(hasattr(obj, 'x')) # False
Python
# 批量动态属性设置
def set_attributes(obj, attrs_dict):
for name, value in attrs_dict.items():
setattr(obj, name, value)
class Config:
pass
config = Config()
set_attributes(config, {
'host': 'localhost',
'port': 8080,
'debug': True
})
print(config.host, config.port) # localhost 8080
setattr 与 delattr
Python
class Validated:
"带验证的属性设置"
def __setattr__(self, name, value):
# 验证逻辑
if name == 'age' and value < 0:
raise ValueError("age cannot be negative")
if name == 'name' and not isinstance(value, str):
raise TypeError("name must be string")
# 存储到 __dict__(避免无限递归)
self.__dict__[name] = value
def __delattr__(self, name):
if name == 'id':
raise AttributeError("id cannot be deleted")
del self.__dict__[name]
v = Validated()
v.name = "Alice"
v.age = 30
# v.age = -1 # ValueError
# v.name = 123 # TypeError
del v.age
# del v.id # AttributeError(需要先定义id)
注意:在
__setattr__中使用self.attr = value会导致无限递归,必须直接操作__dict__。
getattr 与 getattribute
Python
class LazyAttributes:
"延迟加载属性"
_data = {
'config1': 'value1',
'config2': 'value2',
}
def __getattr__(self, name):
"仅在属性不存在时调用"
if name in self._data:
print(f"Loading {name}...")
return self._data[name]
raise AttributeError(f"No attribute '{name}'")
obj = LazyAttributes()
print(obj.config1) # Loading config1... value1
print(obj.config1) # value1(第二次直接返回,已缓存?不,未缓存)
# 添加到 __dict__ 后不再触发 __getattr__
obj.config1 = "cached"
print(obj.config1) # cached(不触发 __getattr__)
Python
class InterceptAll:
"拦截所有属性访问"
def __getattribute__(self, name):
print(f"Accessing: {name}")
# 必须用 super() 避免递归
return super().__getattribute__(name)
def __getattr__(self, name):
print(f"Missing: {name}")
return f"default_{name}"
obj = InterceptAll()
obj.x = 10
print(obj.x) # Accessing: x → 10
print(obj.y) # Accessing: y → Missing: y → default_y
动态方法添加
Python
class DynamicClass:
pass
# 添加实例方法
def greet(self, name):
return f"Hello, {name}! I'm {self.name}"
obj = DynamicClass()
obj.name = "Dynamic"
import types
obj.greet = types.MethodType(greet, obj)
print(obj.greet("World")) # Hello, World! I'm Dynamic
# 添加到类(所有实例共享)
DynamicClass.greet = greet
obj2 = DynamicClass()
obj2.name = "Another"
print(obj2.greet("User")) # Hello, User! I'm Another
属性代理模式
Python
class Proxy:
"属性代理"
def __init__(self, target):
self._target = target
def __getattr__(self, name):
# 转发到目标对象
return getattr(self._target, name)
def __setattr__(self, name, value):
if name == '_target':
# 特殊属性直接存储
super().__setattr__(name, value)
else:
# 其他属性转发
setattr(self._target, name, value)
class RealObject:
def __init__(self):
self.data = "original"
real = RealObject()
proxy = Proxy(real)
print(proxy.data) # original
proxy.data = "proxied"
print(real.data) # proxied(目标对象也被修改)
slots 限制动态属性
Python
class Restricted:
"限制动态属性"
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
obj = Restricted("Alice", 30)
print(obj.name) # Alice
# obj.email = "test" # AttributeError
# obj.__dict__ # AttributeError(无 __dict__)
# 优点:内存效率更高,属性访问更快
# 缺点:无法动态添加属性,无法使用 __dict__
要点总结
- **
__dict__**存储实例属性,类属性存储在类的__dict__ - **
setattr/getattr/delattr**是动态属性操作的内置函数 - **
__setattr__**拦截属性设置,必须操作__dict__避免递归 - **
__getattr__处理缺失属性,__getattribute__**拦截所有访问 - **
__slots__**限制动态属性,提升内存效率
📝 发现内容有误?点击此处直接编辑