排除指定赋值方式,为__init__属性分配属性名作为值是否可行?
问题与解决方案
原代码问题分析
你提供的代码触发RuntimeError: dictionary changed size during iteration有两个核心原因:
- 遍历
self.__dict__时,执行self.att = att会往字典里新增att键,导致遍历过程中字典大小改变,触发错误。 - 赋值逻辑错误:
self.att = att只是给名为att的属性赋值,并没有给遍历到的long_name_a、long_name_b等目标属性赋值。
可行解决方案
排除手动逐个赋值的方式,有两种通用方法可以批量给__init__中定义的属性分配属性名作为值:
方法1:遍历属性名快照
先将当前__dict__的属性名转换成固定列表(快照),再遍历这个列表,用setattr完成正确赋值:
class New: def __init__(self): self.long_name_a = None self.long_name_b = None self.add_value() def add_value(self): # 生成当前属性名的固定列表,避免遍历中字典变化 attr_names = list(self.__dict__.keys()) for name in attr_names: setattr(self, name, name) new = New() assert new.long_name_a == 'long_name_a' assert new.long_name_b == 'long_name_b'
方法2:提前定义属性列表
如果能提前确定要处理的属性名,可以在__init__中先定义列表,再批量赋值:
class New: def __init__(self): # 提前列出需要初始化的属性名 target_attrs = ['long_name_a', 'long_name_b'] for name in target_attrs: setattr(self, name, name) new = New() assert new.long_name_a == 'long_name_a'
这两种方法都不需要手动逐个给属性赋值,且能避免遍历字典时的大小变化错误。
内容的提问来源于stack exchange,提问作者aeiou
相关产品推荐
相关产品推荐

