Python:从嵌套字典创建类对象及实现迭代的问题解决
问题描述
我正在学习Python自动化脚本开发,需要实现以下功能:从配置文件读取多段配置(段数可变,每段变量数量固定),生成嵌套字典,再基于该字典创建类对象——每个配置段对应一个独立对象,段内变量作为对象的属性。
配置文件示例:
[SECTION_01] name = 'name_01' zone = 'zone_01' size = 'size_01' specific_to_SECTION_01 = '' [SECTION_02] name = 'name_02' zone = 'zone_02' size = 'size_02' specific_to_SECTION_02 = '' ... etc.
我已写出部分代码,用setattr()生成了嵌套字典并作为类的输入,但后续处理遇到问题:
import configparser config = configparser.ConfigParser() config.read("ini_file.ini") class MyClass(): def __init__(self, dictionary) for section in dictionary: for k, v in dictionary[section].items() setattr(self, k, v) my_dict = {} for section in config.sections(): if section.startwith('SECTION'): my_dict[section] = {} for key, value in config.items(section): my_dict[section][key] = value
遇到的具体问题:
- 尝试遍历
MyClass实例时,报错MyClass object is not iterable;添加__iter__方法后又出现TypeError: iter() returned non-iterator of type MyClass(),不知道如何正确实现迭代逻辑。 - 直接遍历
my_dict实例化MyClass时,最终只能得到最后一个配置段的对象。
错误分析与解决方法
1. 先修正基础代码的语法错误
代码里存在几处语法和拼写问题,先修正:
__init__方法定义末尾缺少冒号:- 循环语句末尾缺少冒号
: startwith拼写错误,应为startswith- 可以用
dict(config.items(section))简化段内字典的生成
修正后的基础代码:
import configparser config = configparser.ConfigParser() config.read("ini_file.ini") class MyClass(): def __init__(self, dictionary): # 传入单段配置字典,直接将键值对设为对象属性 for k, v in dictionary.items(): setattr(self, k, v) my_dict = {} for section in config.sections(): if section.startswith('SECTION'): my_dict[section] = dict(config.items(section))
2. 正确为每个配置段创建独立对象
你之前的MyClass初始化逻辑错误:把整个嵌套字典传入,导致所有配置段的属性都混到了同一个对象里。正确的做法是遍历my_dict的每个配置段,将单段的字典传入MyClass,逐个创建对象并存储。
用字典存储所有对象(键为配置段名,值为对应实例):
# 存储所有配置段对应的对象 section_objects = {} for section_name, section_data in my_dict.items(): section_objects[section_name] = MyClass(section_data) # 调用示例 print(section_objects['SECTION_01'].name) # 输出 'name_01' print(section_objects['SECTION_02'].zone) # 输出 'zone_02'
3. 解决"仅得到最后一个对象"的问题
之前遍历my_dict只保留最后一个对象,是因为你在循环中反复给同一个变量赋值,覆盖了之前的实例。解决方法就是用容器(字典/列表)把每个实例都存起来,比如上面的section_objects字典。
4. 关于MyClass可迭代的问题
你的场景其实不需要让MyClass实例可迭代,因为每个实例对应单个配置段,本身不是集合。如果非要实现属性迭代(比如遍历对象的所有属性),可以这样修改类:
class MyClass(): def __init__(self, dictionary): # 更简洁的方式将字典转为对象属性 self.__dict__.update(dictionary) def __iter__(self): # 返回属性名称的迭代器 return iter(self.__dict__.keys())
但这个功能对你的需求来说并非必要,直接遍历存储对象的容器即可。
内容的提问来源于stack exchange,提问作者ben
相关产品推荐
相关产品推荐

