在Python中初始化对象列表

23 投票
4 回答
72662 浏览
提问于 2025-04-15 16:26

我想要初始化一个包含对象的数组或列表,这些对象不是空的——也就是说,类的构造函数会生成数据。在C++和Java中,我会这样做:

Object lst = new Object[100];

我查了一下,但有没有什么Python的方式可以做到这一点呢?

这个方法并没有像我想的那样工作(我得到了100个指向同一个对象的引用):

lst = [Object()]*100

不过这个方法似乎达到了我想要的效果:

lst = [Object() for i in range(100)]

列表推导在我看来(从思维上讲)似乎是“很多”工作,但在Java中这件事是如此简单。

4 个回答

2

我觉得用列表推导式是最简单的方法,但如果你不喜欢这种方式,当然还有其他方法可以实现你想要的效果——就是调用一个函数100次,不传入任何参数,来生成一个包含100个元素的新列表。例如,itertools库就能做到这一点:

>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))

或者,如果你真的喜欢传统的方法,可以使用mapapply

>>> lst = map(apply, 100*[Object], 100*[()])

需要注意的是,这些方法在工作量上基本是一样的(无论是概念上还是实际操作上都很小;-))。如果Object需要传入一个参数,而不是不传参数,那么工作量也是差不多的——或者说,如果Object实际上是一个函数而不是一个类型。

从你惊讶于这个任务可能需要“和列表推导式一样多的工作量”来看,你似乎认为每种语言都应该特别处理“无参数调用类型”的情况,而不是其他类型的调用。但我不明白为什么这个特定的情况如此重要,值得与其他情况区别对待。因此,我个人很高兴Python没有单独对这个情况进行特殊处理,而是像处理其他类似的用法一样,简单而直接地处理它!-)

16

你需要注意的是,Python中相当于Java代码(创建一个包含100个null对象引用的数组):

Object arr = new Object[100];

或者C++代码:

Object **arr = new Object*[100];

是:

arr = [None]*100

而不是:

arr = [Object() for _ in range(100)]

第二种情况和Java的效果是一样的:

Object arr = new Object[100];
for (int i = 0; i < arr.lenght; i++) {
    arr[i] = new Object();
}

实际上,Python在初始化复杂数据结构方面的能力要比Java强得多。


注意:

C++代码:

Object *arr = new Object[100];

需要做的工作和Python的列表推导式差不多:

  • 为100个对象分配连续的内存

  • 为每个对象调用Object::Object()构造函数

而且结果会是一个完全不同的数据结构。

46

在Python中,没有像C++那样的方法可以自动为数组中的每个元素调用Object()构造函数(在Java中,新的数组每个元素默认会被初始化为null,特别是对于引用类型)。

我觉得你用列表推导式的方法是最符合Python风格的:

lst = [Object() for i in range(100)]

如果你不想用到变量i,在Python中有个约定是用_来表示一个不重要的变量,也就是说这个变量的值你不在乎:

lst = [Object() for _ in range(100)]

如果你想要一个和Java中类似的结构,当然可以使用*

lst = [None] * 100

撰写回答