2010-07-01 39 views
4

有人能指出我做错了什么或我的理解错误吗?我在做什么错? Python对象实例化保持以前实例化的数据?

对我来说,下面实例化两个对象的代码似乎应该为每个实例化都有单独的数据。

class Node: 
    def __init__(self, data = []): 
     self.data = data 

def main(): 
    a = Node() 
    a.data.append('a-data') #only append data to the a instance 

    b = Node() #shouldn't this be empty? 

    #a data is as expected 
    print('number of items in a:', len(a.data)) 
    for item in a.data: 
     print(item) 

    #b data includes the data from a 
    print('number of items in b:', len(b.data)) 
    for item in b.data: 
     print(item) 

if __name__ == '__main__': 
    main() 

然而,第二对象是与从第一数据创建的:

>>> 
number of items in a: 1 
a-data 
number of items in b: 1 
a-data 
+1

重复更换构造函数的第一行:http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the- mutable-default-argument,和http://stackoverflow.com/questions/2313075/python-default-value-for-a-function,和其他许多人。任何与“可变”和“默认”有关的事情。 – 2010-07-01 21:34:42

+1

谢谢大家的快速解答。在发布问题之前,我努力寻找这个问题,但无法做到。希望这个问题的标题能够帮助其他人从某个不了解该问题是函数定义中的可变对象的人的角度对其进行谷歌搜索。 – KobeJohn 2010-07-01 21:43:44

回答

7

不能使用一个可变对象作为默认值。所有对象将共享相同的可变对象。

这样做。

class Node: 
    def __init__(self, data = None): 
     self.data = data if data is not None else [] 

当您创建类定义时,它会创建[]列表对象。每次创建该类的实例时,都会将相同的列表对象用作默认值。

+0

Aaah。然后,我一直在修改我所有程序中的类定义。非常感谢您提供清晰简洁的答案。 – KobeJohn 2010-07-01 21:37:48

+0

我更喜欢这种语法:self.data = data或[] – 2010-07-01 22:04:06

+2

@Matthew J Morrison:不同的是,将错误的数据传递给数据,然后中断。 – 2010-07-01 22:51:16

2

当为函数或方法提供默认值时,通常需要提供不可变对象。如果您提供一个空列表或一个空字典,您将最终收到所有对该函数或共享该对象的方法的调用。

一个很好的解决方法是:

def __init__(self, data = None): 
    if data == None: 
     self.data = [] 
    else: 
     self.data = data 
+0

在这种特殊情况下可以像这样'cutify': 'self.data = data或[]' – 2010-07-01 22:57:28

3

的问题是在这条线:

def __init__(self, data = []): 

当你写data = []设置一个空列表作为该参数的默认值,巨蟒仅创建列表一次,并且每次调用方法时都使用相同的列表,而没有明确的data参数。在你的情况下,在创建ab时会发生这种情况,因为你没有给出构造函数的明确列表,所以ab都使用与它们的data列表相同的对象。对一个人所做的任何改变都会反映在另一个人身上。

为了解决这个问题,我建议用

def __init__(self, data=None): 
    if data is None: 
     data = []