如何在Python中创建一个空列表的列表或元组?

41 投票
5 回答
45695 浏览
提问于 2025-04-16 05:07

我想逐步填充一个列表或者一个包含列表的元组,想要的效果大概是这样的:

result = []
firstTime = True
for i in range(x):
    for j in someListOfElements:
        if firstTime:
            result.append([f(j)])
        else:
            result[i].append(j)

为了让代码看起来更简洁优雅,我想先准备一个空列表的列表。

result = createListOfEmptyLists(x)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

但是,预先准备这个部分对我来说不是很明显。当我写 result = [[]] * x 的时候,我得到的是一个包含 x 个指向同一个列表的引用的列表,这样后面的输出结果是:

result[0].append(10)
print result

是这样的:

[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]

我可以使用一个循环(result = [[] for i in range(x)]),但我在想有没有不使用循环的方法。

难道得到我想要的结果就只有这个办法吗?

5 个回答

5

你可以写一个简单的生成器函数。这个函数不仅仅适用于这个特定的情况,所以我会稍微泛化一下。听着:

def create(n, constructor=list):
    for _ in xrange(n):
        yield constructor()

然后,如果你想创建一个列表的列表,

result = list(create(10))

或者创建一个空字典的列表,

result = list(create(20, dict))

还有(为了完整性)创建一个空的Foos列表,

result = list(create(30, Foo))

当然,你也可以把上面的任何东西做成一个元组。要让它支持构造函数的参数也不难。我可能会让它接受一个函数,这个函数接受一个索引并返回要传给构造函数的参数。

最后一个想法是,因为我们对constructor的唯一要求是它必须是可调用的,所以你甚至可以传递任何返回你想要的列表内容的东西。比如一个从数据库查询中提取结果的绑定方法。这段代码其实很有用,就三行。

7

其实,要创建这样一个列表,没有办法完全避免使用某种循环。不过,有很多方法可以把循环隐藏起来,比如用 [[]] * x 这种写法就把循环给隐藏了。还有一种叫做列表推导式的方式,它在一个表达式中“隐藏”了循环(不过这点还是挺明显的)。另外,还有 map(list, [[]]*x) 这种写法,它里面有两个隐藏的循环(一个是在 [[]] * x 中,另一个是在 map 中,用 list() 创建每个列表的副本)。

另外,你也可以选择不提前创建一个列表的列表。其他的回答已经介绍了简单的方法,但如果这些方法不适合你的需求,还有其他的选择。例如,你可以写一个函数,根据需要往 result 列表里添加空列表,然后调用这个函数:

def append(L, idx, item):
    while len(L) <= idx:
        L.append([])
    L[idx].append(item)

for i in range(x):
    for j in someListOfElements:
        append(result, i, j)

或者,你可以使用 collections.defaultdict(list) 来代替普通的列表:

import collections
result = collections.defaultdict(list)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

这样做的好处是可以使用已经存在的类型,工作量会少一些,但这也意味着你现在得到的是一个字典(用整数作为索引),而不是列表,这可能符合你的需求,也可能不符合。你还可以创建一个几乎像列表一样的类,但它会在自己内部添加新的列表,而不是抛出索引错误,比如:

import UserList
class defaultlist(UserList.UserList):
    def __getitem__(self, idx):
        while len(self) <= idx:
            self.append([])
        return UserList.UserList.__getitem__(self, idx)

result = defaultlist()
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)
53
result = [list(someListOfElements) for _ in xrange(x)]

这段代码会创建 x 个不同的列表,每个列表里都有一份 someListOfElements 列表的副本(列表里的每个项目是通过引用的,但列表本身是一个副本)。

如果这样理解更容易,可以考虑使用 copy.deepcopy(someListOfElements)

生成器、列表推导式等东西被认为是非常 python 风格 的写法。

撰写回答