两个继承Higher类的子类实例化后self.list_of重复追加next原因
问题根本原因
这是Python中可变类型作为方法默认参数的经典共性问题,成因如下:
- Python的函数/方法在定义阶段就会计算默认参数的取值,存储在函数对象的
__defaults__属性中,不会在每次调用时重新生成默认值。如果默认参数是列表、字典这类可变类型,所有未显式传入该参数的调用,都会共用同一个可变对象。 - 你代码中
Higher类的__init__方法默认参数list_of = ['item1', 'item2'],这个列表在类定义完成时就已经创建,是全局共享的同一对象。 - 第一次实例化
NumberOne时未传入list_of参数,直接使用该共享列表,执行self.list_of += ['next']直接修改了共享列表的内容,此时列表变为['item1', 'item2', 'next']。 - 第二次实例化
NumberTwo时同样未传入list_of,还是使用这个已经被修改过的共享列表,再次执行+= ['next']后列表变为['item1', 'item2', 'next', 'next'],因此最终打印m.list_of得到不符合预期的结果。
你可以在原代码的__init__方法中加入print(id(list_of))验证,两次实例化打印的内存地址完全一致,可证明两次操作的是同一个列表对象。
修复方案
标准规避方式是将可变类型默认参数的默认值设为None,在方法内部每次调用时单独初始化可变对象,避免共用:
class Higher: def __init__(self, list_of: list = None,): # 每次调用时不传参数则新建独立列表 if list_of is None: list_of = ['item1', 'item2'] self.list_of = list_of self.list_of += ['next'] class NumberOne(Higher): def __init__(self,**kwargs): super().__init__(**kwargs) class NumberTwo(Higher): def __init__(self,**kwargs): super().__init__(**kwargs) if __name__=="__main__": n = NumberOne() m = NumberTwo() print(m.list_of) # 输出为预期的 ['item1', 'item2', 'next']
内容的提问来源于stack exchange,提问作者granddejeuner
相关产品推荐
相关产品推荐

