Python 改变列表中的元素

Python 改变列表中的元素,python,coding-style,Python,Coding Style,我有一个布尔值列表,偶尔我会将它们全部重置为false。在首次将重置写入以下内容后: for b in bool_list: b = False 我发现它不起作用。我花了一点时间挠头,然后想起它当然不会起作用,因为我只是改变了对bool的引用,而不是它的值。所以我重写为: for i in xrange(len(bool_list)): bool_list[i] = False 一切正常。但我发现自己在问,“这真的是改变列表中所有元素的最具实用性的方法吗?”还有其他更有效或更

我有一个布尔值列表,偶尔我会将它们全部重置为false。在首次将重置写入以下内容后:

for b in bool_list:
    b = False
我发现它不起作用。我花了一点时间挠头,然后想起它当然不会起作用,因为我只是改变了对bool的引用,而不是它的值。所以我重写为:

for i in xrange(len(bool_list)):
    bool_list[i] = False

一切正常。但我发现自己在问,“这真的是改变列表中所有元素的最具实用性的方法吗?”还有其他更有效或更清晰的方法吗?

如果您只对列表进行了一次引用,以下方法可能更简单:

bool_list = [False] * len(bool_list)
这将创建一个新列表,其中填充了
False
元素


请参阅我对的回答以了解类似的示例。

我不会使用范围和长度。使用enumerate()要干净得多


在这种情况下,它留下了一个未使用的变量,但在我看来,它仍然看起来更干净。性能也没有明显的变化。

对于int、bool和string等值类型,您的第二个示例非常漂亮。您的第一个示例适用于任何引用类型,如类、dict或其他列表。

如果您愿意使用数组,那么使用数组切片实际上很容易做到这一点

import numpy

bool_list = numpy.zeros((100,), dtype=numpy.bool)

# do something interesting with bool_list as if it were a normal list

bool_list[:] = False
# all elements have been reset to False now

以下是另一个版本:

bool_list = [False for item in bool_list]
我想

bool_list = [False for element in bool_list]
就像它得到的一样。在python中使用这样的列表通常也应该比使用for循环更快

bool_list[:] = [False] * len(bool_list)

摘要 就性能而言,numpy或列表乘法显然是赢家,因为它们比其他方法快10-20倍

我对提出的各种选项进行了一些性能测试。我在Linux(Ubuntu 8.10)上使用了Python2.5.2和1.5GHz的奔腾M

原件:

python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False] * len(bool_list)'
1000个循环,最好为3:280 usec/循环

基于切片的列表替换:

python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False] * len(bool_list)'
1000个循环,最好3个:每个循环215 usec

使用生成器进行基于切片的替换:

python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False] * len(bool_list)'
1000个循环,最好3个:每个循环265 usec

枚举

python timeit.py -s 'bool_list = [True] * 1000' 'for i, v in enumerate(bool_list): bool_list[i] = False'
python timeit.py -s 'import numpy' -s 'bool_list = numpy.zeros((1000,), dtype=numpy.bool)' 'bool_list[:] = False'
1000个循环,最好为3:385 usec/循环

Numpy

python timeit.py -s 'bool_list = [True] * 1000' 'for i, v in enumerate(bool_list): bool_list[i] = False'
python timeit.py -s 'import numpy' -s 'bool_list = numpy.zeros((1000,), dtype=numpy.bool)' 'bool_list[:] = False'
10000个循环,最好3个:每个循环15.9 usec

基于切片的列表乘法替换:

python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False] * len(bool_list)'
10000个循环,最好3个:每个循环23.3 usec

引用替换为列表乘法

 python timeit.py -s 'bool_list = [True] * 1000' 'bool_list = [False] * len(bool_list)'

10000个循环,每个循环3:11.3 usec的最佳值

被否决,因为他表示需要在现有列表中执行操作。被否决是因为“现有列表”可以通过赋值语句轻松地替换为新列表。此外,如果你想更改现有列表,可以将其更改为bool_list[:]=[False]*len(bool_list)如果这是一个非常大的列表,那么这段代码可能不好,因为您实际上是在制作列表的两个副本。但它应该在95%的情况下都能工作,这并不是很像蟒蛇。布尔值列表有什么珍贵之处,以至于你无法重建它?您能提供更多的上下文吗?在本例中,没有任何东西禁止重建列表。只有在您不尝试更改列表中包含的项时,第一个示例才会“起作用”。如果你在a:x.foo()中为x做,那当然没关系。然而,如果a是一个dict列表,那么对于a:x={}中的x,由于与原始问题相同的原因,它并没有达到预期的效果。您甚至不需要v变量,这是过度复杂的明确指标。简单的列表理解就能完成任务。为了看起来更好,我还是会投赞成票。速度上没有明显的差别。一个虚拟变量是值得的。我想这可以归结为个人品味的有效性,在所有单独的集合项目中都是如此。为什么要重复前面的答案呢?为什么不投另一个答案?我不确定这个答案有什么不同之处。也许我遗漏了什么。你能修改或扩大你的答案来强调这些独特的信息吗?我很高兴我能给他们时间安排。到目前为止,我一直认为列表乘法很简洁,但可能很慢。这是一个很好的总结!你应该把这个标记为答案。我不知道numpy跑得那么快。之所以选择它,是因为这种风格的效果是明确的,不受列表中只有一个引用的限制,并且顶级的性能非常出色。