Python __init__参数问题

时间:2010-01-31 05:39:31

标签: python class list identity equality

我很难理解作为列表的类init参数会发生什么 像:

class A(object):
    def __init__(self, argument=[]):  
        self.argument = argument[:]  

或:

def __init__(self,argument=None):  
    self.arguments = arguments or []  

或:

def __init__(self, argument=[]):  
    self.argument = argument  

这是不可能的,因为每个A对象的默认值都指向同一块内存。我真的不明白这里发生了什么以及它是如何发生的。

3 个答案:

答案 0 :(得分:6)

这是众所周知的python gotcha

基本上,该参数的默认值是在首次定义方法时创建的,并且因为它是一个可变对象(在本例中是一个列表),所以即使它已经更改,它也只是引用同一个对象,甚至在随后的方法调用中。

处理这类案件的通常方法是像第二个例子那样对待它:

def __init__(self, arguments=None):  
    self.arguments = arguments or []

但是,如果您想要做的是拥有包含所有参数的列表,则可以使用Python的argument unpacking

它的工作原理如下:

def my_function(*args):
    print args

然后,您将在您的方法中访问传递了所有参数的元组。所以,如果你这样调用你的函数:

>>> my_function(1, 2, 3)

您的输出如下:

(1, 2, 3)

很酷的是,你总是可以用对开的方式使用它,所以,假设你有一个列表(或元组),并且你希望将列表中的每个项目作为函数的位置参数传递。你会这样做:

>>> my_list = [1, 2, 3]
>>> my_function(*my_list)

并且,就您的功能而言,它与之前的呼叫相同。

您应该阅读documentation that I pointed to,以及defining functions更深入的部分。

答案 1 :(得分:4)

列表是在运行定义时创建的,而不是在执行方法时创建的。

答案 2 :(得分:1)

我认为这个问题有点不清楚,但我从中理解的是,你想知道如何传递一个类初始化列表不会使内部对象与你传递的内容对象相同,而是一个副本。如果这不是问题,请告诉我,我会删除这个答案。

简而言之,这是它的工作原理:Python中没有任何内容存储为值的名称。一切都在内部存储为Python对象的指针。当你这样做时:

a = [1,2,3]
b = a

您没有将b设置为a。您正在设置b以引用同一个对象。所以声明:

a is b

是的,因为名称引用了同一个对象。

a = [1,2,3]
b = [1,2,3]
a is b

这将返回false。原因是现在你已经创建了两个不同的对象。这一行:

self.argument = argument[:]

是制作self.argument副本的一种(必要的)方式,因此它不会引用同一个对象。