Python中setattr与getattr优化:动态字典属性添加最佳实践
优化动态字典容器的
add_value方法性能 需求回顾
需要实现一个Container类,支持动态创建任意数量的字典作为实例变量,用户调用add_value时无需提前检查字典是否存在,直接为指定字典追加键值对,目标效果如下:
>>> c = Container() >>> c.add_value(variable="first_dict", key="foo", value=1) >>> c.add_value(variable="first_dict", key="bar", value=2) >>> c.add_value(variable="second_dict", key="foo", value=2) >>> print(c.first_dict) {"foo":1, "bar":2} >>> print(c.second_dict) {"foo":2}
原实现的性能顾虑
原实现通过getattr获取属性、修改后再用setattr赋值,确实存在额外的函数调用开销,尤其是在高频调用add_value的场景下。以下是几种更优的实现方案:
方案1:直接操作实例的__dict__属性
Python实例的所有属性都存储在__dict__字典中,直接访问它可以省去getattr和setattr的函数调用开销:
from typing import Any class Container(): def add_value(self, variable: str, key: Any, value: Any): # 从__dict__获取字典,不存在则创建空字典 dict_obj = self.__dict__.get(variable, {}) dict_obj[key] = value self.__dict__[variable] = dict_obj
说明:直接操作__dict__是性能最高的方式之一,减少了两层函数调用的开销。
方案2:利用__getattr__魔法方法延迟创建字典
通过__getattr__实现属性的延迟初始化,只有当属性不存在时才创建空字典,且因为字典是可变对象,修改后无需重新赋值:
from typing import Any class Container(): def __getattr__(self, name: str): # 访问不存在的属性时自动创建空字典 self.__dict__[name] = {} return self.__dict__[name] def add_value(self, variable: str, key: Any, value: Any): # 直接获取属性(不存在则触发__getattr__创建) getattr(self, variable)[key] = value
说明:这个方案更符合Pythonic风格,仅在第一次访问目标字典时触发创建逻辑,后续调用直接操作字典本身,无需再调用setattr。
方案3:用内部统一字典管理所有动态字典
将所有动态字典集中存储在一个内部字典中,避免污染实例的__dict__,同时通过__getattr__保持外部访问的便利性:
from typing import Any, Dict class Container(): def __init__(self): self._dicts: Dict[str, Dict[Any, Any]] = {} def add_value(self, variable: str, key: Any, value: Any): # 一行完成"获取/创建字典 + 赋值键值对" self._dicts.setdefault(variable, {})[key] = value def __getattr__(self, name: str): if name in self._dicts: return self._dicts[name] raise AttributeError(f"'Container' object has no attribute '{name}'")
说明:dict.setdefault是内置高效方法,能快速完成字典的初始化和键值对赋值;集中管理的方式也让代码更易维护,比如后续可以轻松实现批量操作所有动态字典的功能。
方案对比
- 追求极致性能:优先选择方案1或方案3
- 追求代码优雅和可读性:方案2更合适
- 需要集中管理动态字典:方案3是最佳选择
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

