Python __init__ 参数问题

3 投票
3 回答
4812 浏览
提问于 2025-04-15 18:41

我在理解类初始化参数时遇到了一些问题,特别是当这些参数是列表的时候。比如:

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 个回答

1

我觉得这个问题有点不太清楚,不过我理解的是,你在问为什么把一个类的初始化放到列表里时,内部的对象不是你传进去的那个,而是一个复制品。如果我理解错了,请告诉我,我会删掉这个回答。

简单来说,Python的工作方式是这样的:在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

但这将返回假。原因是现在你创建了两个不同的对象。所以这一行:

self.argument = argument[:]

是一个(必要的)方法,用来复制 self.argument,这样它就不会指向同一个对象了。

4

这个列表是在定义的时候就创建好了,而不是等到方法执行的时候才创建。

6

这是一个大家都知道的关于Python的常见问题。

简单来说,当你第一次定义这个方法时,默认参数就已经创建了。因为这个参数是一个可变对象(在这里是一个列表),所以即使它的内容发生了变化,后续调用这个方法时,它仍然指向同一个对象。

通常处理这种情况的方法是像你第二个例子那样来做:

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

但是如果你想要一个包含所有参数的列表,你可以使用Python的参数解包功能。

它的工作方式是这样的:

def my_function(*args):
    print args

这样一来,你在方法中就可以访问到一个包含所有传入参数的元组。如果你像这样调用你的函数:

>>> my_function(1, 2, 3)

你的输出结果会是:

(1, 2, 3)

有趣的是,你也可以反向使用这个功能。假设你有一个列表(或元组),你想把列表中的每个项作为位置参数传递给你的函数。你可以这样做:

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

对于你的函数来说,这和之前的调用是一样的。

你应该看看我提到的文档,还有关于定义函数的部分,它会讲得更详细。

撰写回答