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
相关产品推荐
相关产品推荐

