Python List vs. Array - 何时使用?

Cor*_*erg 353 python arrays list

如果要创建1d数组,可以将其实现为List,或者使用标准库中的"array"模块.我一直使用列表进行1d数组.

我想要使​​用阵列模块的原因或情况是什么?

它是用于性能和内存优化,还是我错过了一些明显的东西?

Dan*_*ski 415

基本上,Python列表非常灵活,可以保存完全异构的任意数据,并且可以在摊销的常量时间内非常有效地附加.如果你需要有效地缩短和增加你的列表并且没有麻烦,那么它们就是你要走的路.但是他们比C阵列使用更多的空间.

array.array类型,在另一方面,是只在C数组的薄包装.它只能保存同类数据,所有类型都相同,因此它只使用sizeof(one object) * length字节的内存.大多数情况下,您需要在需要将C数组公开给扩展或系统调用时使用它(例如,ioctlfctnl).

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

但是,如果你想对同类数组数据进行数学运算,那么你最好使用NumPy,它可以自动对复杂多维数组上的操作进行矢量化.

简而言之:array.array当你需要一个同质的C数组数据时,除了做数学之外的其他原因是很有用的.

  • numpy.ndarray与array.array具有相同的内存占用吗? (9认同)
  • @NithishInpursuitOfhappiness,Python列表不是链表.它在内部表示为一个数组,具有与Java的ArrayList相同的时间复杂度特征.因此,获取和设置Python列表的第i个元素需要**恒定的时间**.将元素附加到Python列表需要**摊销的常量时间**,因为当空间不足时,数组大小会加倍.在Python列表中间插入元素或从中删除元素需要**O(n)时间**,因为元素需要移位.有关参考,请参阅:https://wiki.python.org/moin/TimeComplexity (6认同)
  • @Gordon,在大型连续数组的情况下它应该非常相似:它们都需要`sizeof(element)`×(元素个数)字节,加上一个小的固定头来进行开销.但是,ndarray有一些处理不连续和稀疏数组的高级选项,我认为一些可插入的策略可以为大型数组分配内存...其中一些高级功能将使用户*更少*内存,而其他一些将提高性能使用*更多*记忆. (5认同)

And*_*dré 62

对于几乎所有情况,正常列表是正确的选择.数组模块更像是C数组上的一个瘦包装器,它为您提供了一种强类型容器(请参阅文档),可以访问更多类似C的类型,例如signed/unsigned short或double,它们不是构建的一部分-in类型.我只说如果你确实需要它就使用数组模块,在所有其他情况下都坚持使用列表.

  • 列表更快,因为对数组"原始"数据的操作需要在读取或写入数组时连续创建和销毁python对象. (36认同)
  • 实际上,我做了一个快速测试 - 我总结了一个包含100M条目的列表和相应数组的相同测试,列表实际上快了大约10%. (12认同)
  • @Moe,正如我在上面的回答中指出的那样,Python的内置`array`不是用来做数学**.如果你尝试使用NumPy的`ndarray`来求和一个10 ^ 8数组的数组,那么它将彻底击败`list`.@tzot对于为什么内置"数组"数学运算缓慢有正确的想法. (7认同)
  • 可能,但从未真正使用它,但运行一些微基准测试会很有趣. (3认同)
  • 我刚刚测试过,numpy 在我的机器上快了 86.6 倍。 (3认同)

Jas*_*ker 48

如果您不知道为什么要使用它,那么阵列模块就是您可能不需要的那种东西之一(请注意我并不是想以一种居高临下的方式说出来!) .大多数情况下,阵列模块用于与C代码接口.为了更直接地回答有关性能的问题:

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

另一方面,列表占用更多内存而不是数组的部分原因是因为python将在使用所有已分配元素时分配一些额外元素.这意味着将项目附加到列表更快.因此,如果您计划添加项目,则可以使用列表.

TL; DR如果您有一个特殊的优化需求,或者您需要与C代码接口(并且不能使用pyrex),我只会使用一个数组.


Kou*_*zdi 18

这是一个折衷!

每个人的优点:

名单

  • 灵活
  • 可以是异类的

数组(例如:numpy数组)

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

  • 问题是指Python中的数组模块;不是 numpy 数组。除了尺寸效率之外,他们没有太多优点。他们并不更快。 (4认同)

Ben*_*ein 13

我的理解是数组存储更有效(即作为连续的内存块与指向Python对象的指针),但我不知道任何性能优势.此外,对于数组,您必须存储相同类型的基元,而列表可以存储任何内容.


gil*_*tay 8

标准库数组对二进制I/O非常有用,例如将int列表转换为要写入波形文件的字符串.也就是说,正如许多人已经指出的那样,如果你要做任何真正的工作,那么你应该考虑使用NumPy.


Ale*_*try 6

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


Dip*_*jar 6

这个答案将总结几乎所有关于何时使用列表和数组的查询:

  1. 这两种数据类型之间的主要区别在于可以对它们执行的操作。例如,您可以将数组除以 3,它将把数组的每个元素除以 3。列表则不能执行相同操作。

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

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

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

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


Hor*_*ude 5

数组只能用于特定类型,而列表可用于任何对象.

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

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

  • 内置的python数组在性能方面并不高效,只是内存方面的. (3认同)

Hep*_*tus 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
Run Code Online (Sandbox Code Playgroud)