Python列表vs.数组-何时使用?

如果你正在创建一个1d数组,你可以将它实现为一个列表,或者使用标准库中的'array'模块。我一直用链表来表示一维数组。

我想要使用数组模块的原因或情况是什么?

它是为了性能和内存优化,还是我遗漏了一些明显的东西?

359160 次浏览

我的理解是数组更有效地存储(例如,作为连续的内存块与指向Python对象的指针相比),但我不知道有任何性能上的好处。此外,使用数组必须存储相同类型的原语,而列表可以存储任何类型的原语。

对于几乎所有情况,普通列表都是正确的选择。arrays模块更像是C数组上的一个薄包装器,它为你提供了一种强类型容器(参见文档),可以访问更多类似C的类型,如有符号/无符号short或double,这些都不是内置类型的一部分。我会说,只有在你真的需要它的时候才使用数组模块,在所有其他情况下,坚持使用列表。

Array只能用于特定类型,而list可以用于任何对象。

数组也只能有一种类型的数据,而列表可以有各种对象类型的条目。

数组对于某些数值计算也更有效。

如果要使用数组,请考虑numpy或scipy包,它们为数组提供了更大的灵活性。

基本上,Python列表非常灵活,可以保存完全异构的任意数据,并且可以非常有效地将它们追加到平摊常数时间中。如果你需要精简和增加你的清单,既省时又省事,他们就是你要去的地方。但它们使用比C数组的空间大得多,部分原因是列表中的每一项都需要构造一个单独的Python对象,即使对于可以用简单的C类型表示的数据(例如floatuint64_t)也是如此。

另一方面,array.array类型只是C数组的一个薄包装器。它只能保存同构数据(也就是说,所有相同类型的数据),因此它只使用sizeof(one object) * length字节的内存。通常,当需要将C数组公开给扩展或系统调用(例如,ioctlfctnl)时,应该使用它。

在Python 2中,array.array也是表示可变的字符串的合理方式。x (array('B', bytes))。然而,Python 2.6+和3。x提供了一个可变的字节字符串bytearray

然而,如果你想在数值数据的齐次数组上执行数学,那么你最好使用NumPy,它可以自动向量化复杂多维数组上的操作。

长话短说:当你出于除了做数学的原因需要一个同构C数据数组时,array.array非常有用。

标准库数组对于二进制I/O非常有用,例如将整型数组转换为要写入wave文件的字符串。也就是说,正如许多人已经注意到的,如果你要做任何实际工作,那么你应该考虑使用NumPy。

数组模块是一种如果你不知道为什么要使用它,你可能不需要的东西(请注意,我并不是试图以一种居高居高下的方式说!)。大多数情况下,数组模块用于与C代码进行交互。为了更直接地回答你关于性能的问题:

在某些用途上,数组比列表更有效。如果你需要分配一个你知道不会改变的数组,那么数组可以更快,使用更少的内存。GvR有一个优化轶事,其中数组模块是赢家(长读,但值得)。

另一方面,列表比数组占用更多内存的部分原因是,当所有分配的元素都被使用时,python会分配一些额外的元素。这意味着向列表中添加项更快。所以,如果你打算添加项目,列表是最好的方法。

我只会使用数组,如果你有一个特殊的优化需求,或者你需要与C代码接口(不能使用派热克斯玻璃)。

这是一种交易!

各有优点:

列表

  • 灵活的
  • 可以是异质的

数组(例如:numpy数组)

  • 统一值数组
  • 均匀
  • 紧凑(尺寸)
  • 高效(功能和速度)
  • 方便

numpy array和list之间的一个重要区别是,数组切片是原始数组的视图。这意味着数据不会被复制,对视图的任何修改都将反映在源数组中。

这个答案将总结几乎所有关于何时使用List和Array的查询:

  1. 这两种数据类型的主要区别在于可以对它们执行的操作。例如,你可以将一个数组除以3,它会将数组的每个元素都除以3。对列表则不能这样做。

  2. 列表是python语法的一部分,因此不需要声明,而在使用数组之前必须声明数组。

  3. 可以在列表中存储不同数据类型的值(异构),而在Array中只能存储相同数据类型的值(同构)。

  4. 数组具有丰富的功能和快速,与列表相比,它广泛用于算术运算和存储大量数据。

  5. 与列表相比,数组占用更少的内存。

关于性能,这里有一些比较python列表、数组和numpy数组的数字(都是2017年Macbook Pro上的python 3.7)。 最终结果是python列表对于这些操作是最快的
# Python list with append()
np.mean(timeit.repeat(setup="a = []", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.054 +/- 0.025 msec


# Python array with append()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.104 +/- 0.025 msec


# Numpy array with append()
np.mean(timeit.repeat(setup="import numpy as np; a = np.array([])", stmt="np.append(a, [1.0])", number=1000, repeat=5000)) * 1000
# 5.183 +/- 0.950 msec


# Python list using +=
np.mean(timeit.repeat(setup="a = []", stmt="a += [1.0]", number=1000, repeat=5000)) * 1000
# 0.062 +/- 0.021 msec


# Python array using +=
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a += array.array('f', [1.0]) ", number=1000, repeat=5000)) * 1000
# 0.289 +/- 0.043 msec


# Python list using extend()
np.mean(timeit.repeat(setup="a = []", stmt="a.extend([1.0])", number=1000, repeat=5000)) * 1000
# 0.083 +/- 0.020 msec


# Python array using extend()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.extend([1.0]) ", number=1000, repeat=5000)) * 1000
# 0.169 +/- 0.034