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

向列表追加XLField对象仅保留最后一个的问题求助

问题:实例化对象后列表中仅最后一个对象重复出现

尝试将DataFrame的每行数据实例化为XLField类对象,追加到列表后,列表中所有元素都是最后一个对象的重复值。在追加前打印对象属性能得到预期不同结果,但遍历列表时全是重复的最后一个值。

核心代码

import pandas as pd

df_dict = pd.read_excel(excel_path).to_dict("records")    
xl_field_list = []
for field in df_dict:
    xl_field = XLField(
        field1=field["Field 1"],
        field2=field["Field 2"],
        field3=field["Field 3"],
        field4=field["Field 4"],
    )
    xl_field_list.append(xl_field)

for f in xl_field_list:
    print(f.field1)

运行结果

0052
0052
0052
0052
0052
0052

XLField类定义

import re

class XLField1:
    def __get__(self, obj, objtype=None):
        return self.value

    def __set__(self, obj, value):
        value = value.upper()
        if not re.fullmatch(r"[A-Z0-9]{2}", value):
            raise ValueError("Check Field 1")
        self.value = value


class XLField2:
    def __get__(self, obj, objtype=None):
        return self.value

    def __set__(self, obj, value):
        value = str(value).zfill(4)
        if not re.fullmatch(r"[0-9]{3,4}", value):
            raise ValueError("Check Field 2")
        self.value = value


class XLField3:
    Days_Of_The_Week = [
        "MONDAY",
        "TUESDAY",
        "WEDNESDAY",
    ]

    def __get__(self, obj, objtype=None):
        return self.value

    def __set__(self, obj, value):
        value = value.upper()
        if value not in XLField3.Days_Of_The_Week:
            raise ValueError("Check Field 3")
        self.value = value


class XLField4:
    INT_OR_COM = ["A", "D"]

    def __get__(self, obj, objtype=None):
        return self.value

    def __set__(self, obj, value):
        value = value.upper()
        if value not in XLField4.INT_OR_COM:
            raise ValueError("Check Field 4")
        self.value = value


class XLField:
    field1 = XLField1()
    field2 = XLField2()
    field3 = XLField3()
    field4 = XLField4()

    def __init__(self, field1, field2, field3, field4):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3
        self.field4 = field4

问题原因

你实现的XLField1、XLField2等是描述符类,但这些描述符把值存在了自身实例(self.value)里,而不是存在被描述的对象(即XLField的实例)中。

XLField类里的field1、field2是类属性,所有XLField的实例共享同一个XLField1、XLField2实例。每次给self.field1赋值时,实际是修改了类属性中那个唯一的XLField1实例的value,后面的赋值会覆盖前面的,最终所有实例访问field1时,都会取到最后一次赋值的value。


解决方案

修改描述符类,把值存在被描述的对象(obj)上,而不是描述符自身:

修正后的描述符类代码

import re

class XLField1:
    def __get__(self, obj, objtype=None):
        return obj._field1

    def __set__(self, obj, value):
        value = value.upper()
        if not re.fullmatch(r"[A-Z0-9]{2}", value):
            raise ValueError("Check Field 1")
        obj._field1 = value


class XLField2:
    def __get__(self, obj, objtype=None):
        return obj._field2

    def __set__(self, obj, value):
        value = str(value).zfill(4)
        if not re.fullmatch(r"[0-9]{3,4}", value):
            raise ValueError("Check Field 2")
        obj._field2 = value


class XLField3:
    Days_Of_The_Week = [
        "MONDAY",
        "TUESDAY",
        "WEDNESDAY",
    ]

    def __get__(self, obj, objtype=None):
        return obj._field3

    def __set__(self, obj, value):
        value = value.upper()
        if value not in XLField3.Days_Of_The_Week:
            raise ValueError("Check Field 3")
        obj._field3 = value


class XLField4:
    INT_OR_COM = ["A", "D"]

    def __get__(self, obj, objtype=None):
        return obj._field4

    def __set__(self, obj, value):
        value = value.upper()
        if value not in XLField4.INT_OR_COM:
            raise ValueError("Check Field 4")
        obj._field4 = value


class XLField:
    field1 = XLField1()
    field2 = XLField2()
    field3 = XLField3()
    field4 = XLField4()

    def __init__(self, field1, field2, field3, field4):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3
        self.field4 = field4

说明

  • 每个描述符的__set__方法把处理后的值存入obj的私有属性(比如_field1),而不是描述符自身的self.value
  • __get__方法从obj的私有属性中取值,这样每个XLField实例都有自己独立的属性值,不会互相覆盖

这样修改后,遍历xl_field_list时就能得到每个对象的真实属性值了。


内容的提问来源于stack exchange,提问作者redracer88

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:15:51