生成一个不同的空变量列表

时间:2012-07-25 21:40:37

标签: python initialization mutable

我需要初始化一个默认值列表。如果他们是字符串,这将是整洁的:

list_of_dds = [string] * n

...但是对于可变数据,你会遇到这种方法:

>>> x=[defaultdict(list)] * 3
>>> x[0]['foo'] = 'bar'
>>> x
[defaultdict(<type 'list'>, {'foo': 'bar'}), defaultdict(<type 'list'>, {'foo': 'bar'}), defaultdict(<type 'list'>, {'foo': 'bar'})]

所做的想要的是一个可重复的默认不同的默认实例。我可以这样做:

list_of_dds = [defaultdict(list) for i in xrange(n)]

但是我觉得这里使用列表理解有点脏。我认为这是一种更好的方法。在那儿?请告诉我它是什么。

编辑:

这就是为什么我觉得列表理解不是最理想的。我通常不是预优化类型,但我无法忽略速度差异:

>>> timeit('x=[string.letters]*100', setup='import string')
0.9318461418151855
>>> timeit('x=[string.letters for i in xrange(100)]', setup='import string')
12.606678009033203
>>> timeit('x=[[]]*100')
0.890861988067627
>>> timeit('x=[[] for i in xrange(100)]')
9.716886043548584

2 个答案:

答案 0 :(得分:2)

使用列表推导的方法是正确的。为什么你觉得它很脏?你想要的是一个长度由一些基本集定义的事物列表。列表推导基于某些基本集创建列表。在这里使用列表理解有什么问题?

编辑:速度差异是您尝试做的直接后果。 [[]]*100速度更快,因为它只需要创建一个列表。每次创建一个新列表都比较慢,是的,但如果你真的需要100个不同的列表,你必须期望它更慢。

(它不会在你的字符串示例上每次创建一个新的字符串,但它仍然较慢,因为列表理解不能提前“知道”所有元素将是相同的,所以它仍然必须每次都重新评估表达式。我不知道列表comp的内部细节,但是可能还有一些列表调整大小的开销,因为它不一定知道可迭代的索引的大小,所以它不能预先分配列表。此外,请注意,您的字符串示例中的一些减速是由于在每次迭代时查找string.letters。在我的系统上使用timeit.timeit('x=[letters for i in xrange(100)]', setup='from string import letters')代替---查找string.letters只有一次---将时间减少约30%。)

答案 1 :(得分:1)

列表理解正是你应该使用的。

列表乘法的问题是创建了包含单个可变对象的列表,然后然后尝试复制它。但是,通过尝试从对象本身复制对象,用于创建它的代码不再相关。没有你用做对象会做你想要的,运行用于创建它的代码N次,因为对象不知道用什么代码来创建它。

您可以使用copy.copy或copy.deepcopy来复制它,但这会让您回到同一条船上,因为复制/深度复制的调用只会成为您运行N次所需的代码。

列表理解非常适合这里。怎么了?