当array.array比列表更有效时?

时间:2016-12-23 20:25:22

标签: python arrays list

我正在阅读这本书'Fluent Python'当我遇到作者陈述

的句子时
  

如果你需要存储1000万个浮点值,那么数组就很多了   效率更高,因为阵列实际上并不完全成熟   对象,但只有表示其机器值的压缩字节 -   就像C语言中的数组一样。

我无法理解作者试图传达的内容。他说的是什么'打包字节' ?什么'打包字节存储'意思 ? 。 python列表如何存储它?为什么不以那种方式存储它,如果这使它变得有效呢?

2 个答案:

答案 0 :(得分:9)

让我们说你正在处理8字节的浮点数。 "打包字节"在这种情况下意味着有一个专用的分配内存块,其中前8个字节代表第一个浮点数,然后紧接着接下来的8个字节代表下一个浮点数,依此类推,没有浪费。它是存储数据的最节省空间的方式(至少在没有压缩的情况下)。对某些操作来说,它也可能是最节省时间的(例如,数组算术运算)。

Python list不会以这种方式存储东西。首先,一个列表元素可以是浮点数,但 next 一个可能是其他类型的对象。另外,您可以删除,插入或替换列表中的项目。其中一些操作涉及动态地延长或缩短列表。如果项目存储为压缩字节,则所有时间和内存都 。 Python list类被设计为尽可能通用,在各种类型的操作的效率之间做出妥协。

最重要的区别可能是Python list在其底层C实现中是一个容器,其中包含指向对象的指针,而不是一个装满原始对象内容的容器。其中一个含义是对{em>相同 Python对象的多个引用可以出现在list中。另一个是可以非常有效地完成更改特定项目。例如,让我们说列表中的第一项a[0]是一个整数,但是您想要用占用更多内存的字符串替换它,例如a[0] = "There's a horse in aisle five."打包数组必须(a)腾出更多空间,将所有其余数组内容转移到内存中,(b)分别更新某种项目大小和类型的索引。但是Python list只需要用另一个指针覆盖一个指针值。

在CPython实现中,指针本身可能仍然(或多或少)打包在内存中。这意味着将新项插入list通常仍然效率低下(相对于使用Python list实现时的方式,例如,引擎盖下的链接列表结构)。

一般来说,没有绝对的"有效的"或者"效率低下" - 所有哪个资源的问题,什么(限制)内容容器中有类型,如何您打算转换容器或其内容。

答案 1 :(得分:4)

在幕后,Python主要使用指针。 Python列表实际上是一个指针数组(至少在参考实现中)。这是效率低下的部分原因。另一部分是Python通常使用duck-typing,所以在尝试之前你无法判断一个操作是否会对list元素起作用。

当您访问列表元素以对其执行某些操作时,例如调用__add__方法,你必须A)取消引用指向实际对象的指针,B)找出它是否有__add__属性,检查它是否可调用,然后实际进行调用。 / p>

在数组中,您知道预先存储的数据类型,因此您知道它拥有的所有属性以及所有操作。最重要的是,所有实际数字都被打包成一个单独的内存。列表不是这种情况。由于数字只是Python中的一种对象,因此数字列表实际上是通用对象指针的列表。

总而言之,数组存储原始数字而不是指向包裹数字的大对象的指针,使它们变小。数组预先知道其内容的类型,因此对整个数组应用操作只需要一次检查,而不是像列表一样检查每个元素。