在Python中初始化对象列表
我想要初始化一个包含对象的数组或列表,这些对象不是空的——也就是说,类的构造函数会生成数据。在C++和Java中,我会这样做:
Object lst = new Object[100];
我查了一下,但有没有什么Python的方式可以做到这一点呢?
这个方法并没有像我想的那样工作(我得到了100个指向同一个对象的引用):
lst = [Object()]*100
不过这个方法似乎达到了我想要的效果:
lst = [Object() for i in range(100)]
列表推导在我看来(从思维上讲)似乎是“很多”工作,但在Java中这件事是如此简单。
4 个回答
我觉得用列表推导式是最简单的方法,但如果你不喜欢这种方式,当然还有其他方法可以实现你想要的效果——就是调用一个函数100次,不传入任何参数,来生成一个包含100个元素的新列表。例如,itertools
库就能做到这一点:
>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))
或者,如果你真的喜欢传统的方法,可以使用map
和apply
:
>>> lst = map(apply, 100*[Object], 100*[()])
需要注意的是,这些方法在工作量上基本是一样的(无论是概念上还是实际操作上都很小;-))。如果Object
需要传入一个参数,而不是不传参数,那么工作量也是差不多的——或者说,如果Object
实际上是一个函数而不是一个类型。
从你惊讶于这个任务可能需要“和列表推导式一样多的工作量”来看,你似乎认为每种语言都应该特别处理“无参数调用类型”的情况,而不是其他类型的调用。但我不明白为什么这个特定的情况如此重要,值得与其他情况区别对待。因此,我个人很高兴Python没有单独对这个情况进行特殊处理,而是像处理其他类似的用法一样,简单而直接地处理它!-)
你需要注意的是,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()构造函数
而且结果会是一个完全不同的数据结构。
在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