You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:55:23