Python字典内列表未显式修改却变更问题求助
问题分析与解决
问题描述
执行以下PyQGIS函数时,首次点击按钮正常,但再次执行后,外部文件中的required_attributes["Strasse"]会被自动添加"LÄNGE"和"VOLUMEN"元素,代码中并未显式修改该字典:
def show_selected_button(self): attrbs = required_attributes[self.modeComboBox.currentText()] layers = QgsProject.instance().mapLayersByName(self.layerComboBox.currentText()) layer = layers[0] layer.selectAll() selected_features = layer.getSelectedFeatures() data = [] for i in selected_features: attribute_row = [] for a in attrbs: attrb = i.attribute(name=a) if a == "MITTLEREBR": attrb = round(attrb, 2) attribute_row.append(attrb) laenge = i.geometry().length() vol = laenge * i.attribute(name="DICKE") / 100 * i.attribute(name="MITTLEREBR") attribute_row.append(round(laenge, 2)) attribute_row.append(round(vol, 2)) data.append(attribute_row) attrbs.append("LÄNGE") attrbs.append("VOLUMEN") self.tableWidget.setRowCount(len(data)) self.tableWidget.setColumnCount(len(attrbs)) self.tableWidget.setHorizontalHeaderLabels(attrbs) for i, x in enumerate(data): for j, y in enumerate(x): self.tableWidget.setItem(i, j, QtWidgets.QTableWidgetItem(str(y)))
首次执行时required_attributes["Strasse"]内容:
['EBENE', 'SCHICHTTYP', 'SCHICHTT01', 'SCHICHTT02', 'DICKE', 'MITTLEREBR']
再次执行时内容变为:
['EBENE', 'SCHICHTTYP', 'SCHICHTT01', 'SCHICHTT02', 'DICKE', 'MITTLEREBR', 'LÄNGE', 'VOLUMEN']
原因分析
Python中列表是可变对象,执行attrbs = required_attributes[self.modeComboBox.currentText()]时,attrbs并没有创建新列表,而是直接引用了required_attributes字典中对应键的原列表对象。后续调用attrbs.append()时,实际是在修改原字典里的列表,导致外部文件中的数据被意外改变。
解决方案
给attrbs赋值时,创建原列表的副本,而非直接引用原对象,有三种常用实现方式:
方法1:使用列表copy()方法
修改第一行赋值代码:
attrbs = required_attributes[self.modeComboBox.currentText()].copy()
方法2:使用list()构造函数
attrbs = list(required_attributes[self.modeComboBox.currentText()])
方法3:使用切片语法
attrbs = required_attributes[self.modeComboBox.currentText()][:]
修改后的完整函数示例(以copy()为例):
def show_selected_button(self): # 创建原列表的副本,避免修改原字典中的数据 attrbs = required_attributes[self.modeComboBox.currentText()].copy() layers = QgsProject.instance().mapLayersByName(self.layerComboBox.currentText()) layer = layers[0] layer.selectAll() selected_features = layer.getSelectedFeatures() data = [] for i in selected_features: attribute_row = [] for a in attrbs: attrb = i.attribute(name=a) if a == "MITTLEREBR": attrb = round(attrb, 2) attribute_row.append(attrb) laenge = i.geometry().length() vol = laenge * i.attribute(name="DICKE") / 100 * i.attribute(name="MITTLEREBR") attribute_row.append(round(laenge, 2)) attribute_row.append(round(vol, 2)) data.append(attribute_row) attrbs.append("LÄNGE") attrbs.append("VOLUMEN") self.tableWidget.setRowCount(len(data)) self.tableWidget.setColumnCount(len(attrbs)) self.tableWidget.setHorizontalHeaderLabels(attrbs) for i, x in enumerate(data): for j, y in enumerate(x): self.tableWidget.setItem(i, j, QtWidgets.QTableWidgetItem(str(y)))
修改后,attrbs操作的是原列表的副本,不会影响required_attributes字典中的原始数据,多次执行函数也不会导致原列表被修改。
内容的提问来源于stack exchange,提问作者Malik Meshi
相关产品推荐
相关产品推荐

