Python类列表变量赋值时所有元素值同步变更问题咨询
问题分析与修复:类实例误用导致的共享数据问题
嘿,我一眼就看出问题出在哪了——你一直在操作Container类本身,而不是它的实例对象!这就好比你拿一个班级的花名册(类)去填个人信息,结果所有同学的信息都变成一样的了,因为你改的是班级的模板,不是每个同学的个人档案。
具体错误点拆解
- 初始化时的问题:在
GetFromXML2的__init__方法里,你写了self._data = [Container],这里你把Container这个类直接放进了列表,而不是创建一个Container的实例(也就是Container())。 - 添加元素时的问题:在
add方法里,self._data.insert(index, Container)同样是插入类本身,不是实例。之后你给self._data[index].tag赋值,本质上是在修改Container类的类属性,而不是某个实例的属性——类属性是所有实例共享的,所以最后一次赋值会覆盖之前所有的修改,导致所有元素看起来都变成了新值。
修复方案
只需要把所有引用Container的地方,改成创建它的实例Container()就行,修改后的GetFromXML.py关键部分如下:
#!/usr/bin/python3 import os import xml.etree.ElementTree as ET class GetFromXML2: """ This is version 2 of the class GetFromXML above. For description, scroll up to the beginning of code. """ def __init__(self, data_path=os.path.join(os.path.dirname(__file__), 'data.xml')): self._data_path = data_path if self._data_path == os.path.join(os.path.dirname(__file__), 'data.xml'): print('No path passed during object initialization, therefore default path shown below was used:\n{}'.format(self._data_path)) else: print('A new path was passed during object initialization, the path being used is shown below:\n{}'.format(self._data_path)) self._data = [Container()] # 这里改成创建实例 self._root = None print('Initialization complete, object fully initialized.') def load_data(self): print('Loading data from {}.'.format(self._data_path)) self._root = ET.parse(self._data_path).getroot() for i, k in enumerate(self._root.iter('key')): self.add(i, k.attrib['install'], k.text) def add(self, index, install, tag): if index != 0: self._data.insert(index, Container()) # 这里也改成插入实例 self._data[index].tag = tag self._data[index].install = install class Container: # 额外建议:没必要继承list,你没用到list的任何功能,普通类更清晰 def __init__(self): self._install = False self._tag = '' @property def tag(self): return self._tag @tag.setter def tag(self, value): self._tag = value @property def install(self): return self._install @install.setter def install(self, value): self._install = value
修复原理
当你调用Container()时,Python会创建一个独立的实例对象,每个实例都有自己专属的_install和_tag属性,互相之间完全独立。之前的写法是直接修改类的属性,相当于所有“学生”共用同一份信息,现在每个“学生”都有自己的档案,自然不会互相干扰了。
修复后你再调试,就能看到self._data里每个元素的tag和install都是对应XML节点的正确值,不会再全部同步成最后一个值啦。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

