如何在Python中创建一个空列表的列表或元组?
我想逐步填充一个列表或者一个包含列表的元组,想要的效果大概是这样的:
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 个回答
你可以写一个简单的生成器函数。这个函数不仅仅适用于这个特定的情况,所以我会稍微泛化一下。听着:
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
的唯一要求是它必须是可调用的,所以你甚至可以传递任何返回你想要的列表内容的东西。比如一个从数据库查询中提取结果的绑定方法。这段代码其实很有用,就三行。
其实,要创建这样一个列表,没有办法完全避免使用某种循环。不过,有很多方法可以把循环隐藏起来,比如用 [[]] * 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)
result = [list(someListOfElements) for _ in xrange(x)]
这段代码会创建 x 个不同的列表,每个列表里都有一份 someListOfElements
列表的副本(列表里的每个项目是通过引用的,但列表本身是一个副本)。
如果这样理解更容易,可以考虑使用 copy.deepcopy(someListOfElements)
。
生成器、列表推导式等东西被认为是非常 python 风格 的写法。