You need to enable JavaScript to run this app. Python用for循环追加@classmethod生成对象到列表后全元素为最后一个的问题
优惠活动
大模型
产品
解决方案
定价
更多

Python用for循环追加@classmethod生成对象到列表后全元素为最后一个的问题

问题本质

你的get_task方法从实现逻辑上就存在根本性错误:

  • 类方法的第一个参数接收的是Task类本身(按Python惯例应该命名为cls,写成self本身就容易造成逻辑误导)
  • 你在方法内直接给类对象挂载属性,最后return self,意味着每次调用方法返回的都是同一个全局唯一的Task类对象
  • 循环过程中对属性的修改,本质上是覆盖这个全局类对象的共享属性,不管你往列表里append多少次,所有列表项指向的都是同一个内存地址的类对象
  • 你之前尝试的copy.copy/copy.deepcopy全部无效的核心原因是:Python 中类是元类生成的单例对象,对类本身执行拷贝操作并不会生成新的独立对象,本质还是返回原类的引用。等你执行拷贝时,类对象的属性已经被最后一次循环覆盖成了"test",所有拷贝出来的引用自然全是错误值。
修复方案

修改get_task的返回逻辑,每次从数据库查完字段后,实例化一个全新的Task对象再返回,不要直接返回类本身。
对应你原本的数据库查询逻辑,正确的类实现参考:

class Task(object):
    def __init__(self, taskID, taskName, points, active, complete, approved, assignedUserID, createdByUserID, dateCreated, dateCompleted, frequency):
        self.taskID = taskID
        self.taskName = taskName
        self.points = points
        self.complete = complete
        self.approved = approved
        self.assignedUserID = assignedUserID
        self.createdByUserID = createdByUserID
        self.dateCreated = dateCreated
        self.dateCompleted = dateCompleted
        self.frequency = frequency
        self.homeID = homeID

    @classmethod
    def get_task(cls, taskID):
        t = (taskID,)
        cur = mysql.connection.cursor()
        cur.execute("SELECT * FROM tasks WHERE taskID=%s", t)
        columns = [col[0] for col in cur.description]
        task = [dict(zip(columns, row)) for row in cur.fetchall()]
        # 用查询到的字段值生成全新的Task实例返回
        return cls(
            taskID=taskID,
            taskName=task[0]['taskName'],
            points=task[0]['points'],
            approved=task[0]['approved'],
            assignedUserID=task[0]['assignedUserID'],
            createdByUserID=task[0]['createdByUserID'],
            dateCreated=task[0]['dateCreated'],
            dateCompleted=task[0]['dateCompleted'],
            frequency=task[0]['frequency']
        )

你写的最小可复现示例,修改后的get_task实现如下:

class Task(object):
    def __init__(self, taskID, taskName):
        self.taskID = taskID
        self.taskName = taskName

    @classmethod
    def get_task(cls, index):
        taskIDList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        taskNames = ['Do Dishes', 'Make Bed', 'Laundry', 'Study', 'Laundry', 'Elliptical', 'Elliptical', 'Laundry', 'Elliptical', 'Elliptical', 'Elliptical', 'test']
        # 生成独立实例返回,不要直接修改类本身的属性
        return cls(
            taskID=taskIDList[index],
            taskName=taskNames[index]
        )

修改完成后,每次循环拿到的都是内存独立的Task对象,列表元素之间不会共享引用,打印输出的结果就会符合预期。

注:原实现中存在拼写错误self.aproved,实际对应字段为approved,可在修改时一并修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 06:57:07