Python类实例列表中修改一实例属性致另一变更的原因咨询
为什么修改一个实例的属性会影响另一个?
嘿,这个问题其实是Python里一个非常经典的“陷阱”——可变默认参数的创建时机搞的鬼!
先看你的代码:
class test: def __init__(self, a=[None,None], b=[None,None], c=[None,None]): self.a = a self.b = b self.c = c new = [test(), test()] new[0].a[0] = 15 print(new[1].a) # 结果会是 [15, None],是不是和你看到的一样?
问题根源:默认参数的初始化时机
Python的函数默认参数是在函数定义的时候就完成初始化,而不是每次调用函数时重新创建。也就是说,当你写def __init__(self, a=[None,None]...)的时候,这个[None,None]列表在类定义的阶段就已经被创建出来了。所有没有显式传递a、b、c参数的test实例,都会共享这同一个列表对象。
所以你创建的new[0]和new[1],它们的self.a其实指向的是同一个列表。当你修改new[0].a[0]时,本质上是在修改那个共享的列表,自然new[1].a也会跟着变——因为它们本来就是同一个东西!
解决方法:避免用可变对象当默认参数
标准的Pythonic做法是用None作为默认值,然后在__init__内部初始化可变对象:
class test: def __init__(self, a=None, b=None, c=None): # 如果没有传参数,就创建一个全新的列表 self.a = a if a is not None else [None, None] self.b = b if b is not None else [None, None] self.c = c if c is not None else [None, None]
这样一来,每次调用test()的时候,如果没有传参数,__init__都会创建一个全新的列表。每个实例的a、b、c都是独立的对象,修改其中一个实例的属性就不会影响另一个了。
这个坑其实很多Python新手都会踩,核心就是记住:可变默认参数只会被初始化一次,在函数定义的时候,而不是每次调用时。
内容的提问来源于stack exchange,提问作者Cindy Almighty
相关产品推荐
相关产品推荐

