python类的初始化与默认参数的陷阱
本文将深入探讨python中类的初始化机制,并解释为什么在定义类时使用可变对象作为默认参数会导致意料之外的行为,以及如何避免此类问题。
我们以一个名为list的类为例,观察其初始化方法__init__的不同实现方式对结果的影响。
首先,让我们看第一个例子:
class list(object): def __init__(self): self.list=[] list1=list() list1.list.append('12') list2=list() print(list2.list)
这段代码的输出结果是[]。这是因为在__init__方法中,每次创建list实例时,都会创建一个新的空列表赋给self.list。因此,list1和list2拥有各自独立的列表。
然而,如果我们修改__init__方法,使用一个列表作为默认参数:
class list(object): def __init__(self,list=[]): self.list=list self.str=str list1=list() list1.list.append('12') list2=list() print(list2.list)
这段代码的输出结果却变成了['12']。这与我们直觉上的结果相悖。
问题的关键在于python默认参数的赋值时机。默认参数的值是在定义函数时就确定的,而不是在每次调用函数时确定的。这意味着在上面的第二个例子中,list=[] 只执行一次,在list类定义的时候就创建了一个空列表,之后每次调用__init__方法时,self.list 都指向这个同一个列表。因此,list1修改了这个列表后,list2 使用的也是同一个列表,所以输出了['12']。
为了更好地理解这个问题,我们可以将代码等价地改写成:
defaultlist = [] class list(object): def __init__(self, list=none): if list: self.list = list else: self.list = defaultlist list1 = list() list1.list.append('12') list2 = list() print(list2.list)
这段代码更清晰地展现了默认参数的陷阱:list1 和 list2 的 self.list 都指向同一个 defaultlist。
为了避免这种问题,最佳实践是使用none作为默认参数,并在__init__方法内部进行条件赋值:
class List(object): def __init__(self, list=None): self.list = list if list != None else [] list1 = List() list1.list.append('12') list2 = List() print(list2.list)
这样,每次创建list实例时,都会创建一个新的空列表,避免了共享同一个列表的风险,从而保证了各个实例的独立性。
以上就是Python类初始化:为什么默认参数是可变对象时会出错?的详细内容,更多请关注知识资源分享宝库其它相关文章!
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。