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

Python类实例化异常:调用CombinedPromoList.add_promo时所有Day共享相同StoryPromoList

问题原因

这是Python中可变默认参数的经典陷阱,加上你错误访问类变量导致的误会,具体问题有两个:

  • 你在get_all_promos中打印的self.spl._id是StoryPromoList的类变量,所有实例共享该变量,每次创建新的StoryPromoList实例都会把这个类变量加1,因此所有实例读取到的都是最后一次更新的值(也就是你输出里的6),这让你误以为所有实例是同一个,实际只要打印实例自己的self.spl.id就能看到每个实例的独立编号。
  • StoryPromoList和FeedPromoList的__init__方法使用了list=[]作为默认参数,Python的函数默认参数是在函数定义阶段生成的,不是每次调用函数时重新生成,所以所有未传入自定义list参数创建的实例,都会共享同一个列表对象,往任意一个实例的list里添加内容,所有实例的list都会同步变化,这是你观察到数据异常的核心原因。
  • 额外说明:CombinedPromoList的__init__方法默认参数spl=StoryPromoList()、fpl=FeedPromoList()也存在同样的可变默认参数陷阱,只是你在Day类中创建CombinedPromoList时主动传入了自定义的spl和fpl,所以暂时没有踩到这个坑,建议一并修复。
修复方案

1. 修正StoryPromoList/FeedPromoList的默认参数

将可变默认参数改为None,在初始化方法内部创建新的列表对象:

class StoryPromoList():
    classes = []
    _id = 0
    def __init__(self, list=None):
        self.id=StoryPromoList._id
        StoryPromoList._id += 1
        StoryPromoList.classes.append(self)
        self.list = list if list is not None else []

    def add(self, storypromo:StoryPromo):
        self.list.append(storypromo)

2. 修正CombinedPromoList的默认参数

同理修改默认参数避免后续调用踩坑:

class CombinedPromoList():
    def __init__(self, spl=None, fpl=None) -> None:
        self.spl = spl if spl is not None else StoryPromoList()
        self.fpl = fpl if fpl is not None else FeedPromoList()

    def add_promo(self, promo):
        if promo.type_name() == 'story':
            self.spl.add(promo)
        elif promo.type_name() == 'feed':
            self.fpl.add(promo)

3. 修正打印逻辑

打印实例自身的id属性而非类变量,方便调试:

def get_all_promos(self):
    print(self.spl.id, self.date, self.cpl)
    return {'story_promos': [p for p in self.cpl.spl.list], 'feed_promos': [p for p in self.cpl.fpl.list]}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:57:03