26

Python 根据底层系统架构自动分配整数。不幸的是,我有一个巨大的数据集,需要完全加载到内存中。

那么,有没有办法强制 Python 只对某些整数使用 2 个字节(相当于 C++ 'short')?

4

6 回答 6

40

没有。但是您可以在数组中使用短整数:

from array import array
a = array("h") # h = signed short, H = unsigned short

只要该值保留在该数组中,它将是一个短整数。

于 2008-09-23T10:36:44.307 回答
5

感谢 Armin 指出“数组”模块。我还发现了将 c 风格的结构打包成字符串的“struct”模块:

从文档(https://docs.python.org/library/struct.html):

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
于 2008-09-23T11:34:37.740 回答
3

Armin 对阵列模块的建议可能是最好的。两种可能的选择:

  • 您可以自己创建一个扩展模块,以提供您所追求的数据结构。如果它真的只是一些短裤的集合,那么这很容易做到。
  • 您可以作弊和操纵位,以便将一个数字存储在 Python int 的下半部分,而将另一个数字存储在上半部分。您将编写一些实用程序函数来在您的数据结构中与这些函数进行转换。丑陋,但它可以工作。

值得一提的是,Python 整数对象不是 4 个字节——还有额外的开销。因此,如果您有大量的短裤,那么您可以通过以某种方式(例如数组模块)使用 C 短裤来为每个号码节省两个以上的字节。

不久前,我不得不在内存中保留大量整数,并且带有整数键和值的字典太大(我有 1GB 可用于数据结构 IIRC)。我改用 IIBTree(来自 ZODB)并设法适应它。(IIBTree 中的整数是真正的 C 整数,而不是 Python 整数,当数字大于 32 位时,我将自动切换到 IOBTree)。

于 2008-09-23T11:35:15.227 回答
3

您可以将 NumyPy 的 int 用作 np.int8 或 np.int16。

于 2020-02-12T14:43:53.673 回答
1

您还可以将多个任意大小的整数存储在一个大整数中。

例如如下所示,在 64 位 x86 系统上的 python3 中,1024 位占用 164 字节的内存存储。这意味着平均一个字节可以存储大约 6.24 位。如果你使用更大的整数,你可以获得更高的位存储密度。例如,每字节大约 7.50 位,2**20 位宽整数。

显然,您将需要一些包装逻辑来访问存储在较大整数中的各个短数字,这很容易实现。

这种方法的一个问题是您的数据访问会因为使用大整数运算而减慢。

如果您一次访问大量连续存储的整数以最小化对大整数的访问,那么对长整数的较慢访问将不是问题。

我想使用 numpy 会更容易。

>>> a = 2**1024
>>> sys.getsizeof(a)
164
>>> 1024/164
6.2439024390243905

>>> a = 2**(2**20)
>>> sys.getsizeof(a)
139836
>>> 2**20 / 139836
7.49861266054521
于 2020-01-05T21:25:04.373 回答
1

在 python 中使用 bytearray 基本上是一个 C unsigned char 数组,这将是一个比使用大整数更好的解决方案。操作字节数组没有开销,并且与大整数相比,它的存储开销要少得多。使用 bytearrays 可以获得每字节 7.99+ 位的存储密度。

>>> import sys
>>> a = bytearray(2**32)
>>> sys.getsizeof(a)
4294967353
>>> 8 * 2**32 / 4294967353
7.999999893829228
于 2020-01-06T20:14:01.053 回答