【问题标题】:Python: Declare 2 Byte VariablesPython:声明 2 字节变量
【发布时间】:2014-12-07 05:04:10
【问题描述】:

是否有 python 模块允许我将数字存储在比int 小得多的对象中?

我的内存对于我的一些数据结构来说不够大,所以我想用尽可能少的空间来表示数字。

问题是我将值存储在树结构中

所有整数都是键或值。也许当使用较小的变量时实际大小不会减少太多 - 我不知道。

【问题讨论】:

  • 在 Python 中没有输入数据。
  • 如果你使用numpy数组,你可以输入它们,例如np.array([100, 200, 300], dtype=np.uint8) - 见numpy.dtype
  • @Begueradj Python 数据当然是输入的。值有类型,但名称没有。

标签: python memory numbers int sizeof


【解决方案1】:

看看numpy数组:

>>> import numpy as np
>>> np.array([0, 1, 2, 127, -128], dtype='int8')
array([   0,    1,    2,  127, -128], dtype=int8)

例如,np.int8 将为您提供高效的有符号整数存储空间,最高可达2**7 - 1

警告:超出范围的值将“环绕”而没有任何溢出错误:

>>> np.int8(128)
-128

当然,还有其他的dtype-s,哪个适合你取决于你需要的值的范围。

【讨论】:

  • 问题是我将值存储在树结构中:所有整数都是键或值。也许使用较小的变量时实际大小不会减少太多 - 我不知道。
【解决方案2】:

numpy 的答案很好。另一个更简单的替代方法是使用标准库中的array 模块。

>>> import array
>>> array_of_ints = array.array("I")
>>> sys.getsizeof(array_of_ints)
28L

【讨论】:

    【解决方案3】:

    就我了解您对 numpy 的最后评论而言,您使用的是树状结构。

    您总是可以使用整数数组来存储一棵树。

    例如:

    index 0 = root     1                     5
          0   1   2    3   4   5 ....        15
       +-------------------------------------------------------+
       | 10 | 5 | 1 ||      ......                             |
       +-------------------------------------------------------+
              |   |    ^                     ^
              |   +----+                     |
              +------------------------------+
    

    在此示例中,每个条目都存储在数组的三个条目中,第一个条目是值,其他条目是子项的(相对 -- 乘以 3)索引。

    因此,您可以将任何树状数据结构存储在 array 中。

    唯一的问题是,使用引用编程有点复杂。

    此外,当您的“指针”大小不同时(例如,您需要 >65k 条目——您将需要 32 位整数),您必须使用更大的大小。当然,您也可以将三个值存储在两个甚至三个数组中。只需制作 3 个数组,一个用于值(例如,只有 16 位),两个用于引用。在这种情况下,您不需要自己进行任何乘法运算,因为您的索引将与这些数组中的普通数组索引相同。

    顺便说一句:我也猜想,当您使用 numpy 实现它并让树中的每个条目本身是一个数组或使用仅包含一个值的小对象时,您的胜利会很低,因为 Python对于存储在系统中的任何对象,都有很大的开销。但是当您像示例中那样使用少量数组时,每个数组都是一个对象,并且开销是可以忽略的,因为您将许多条目存储在少量数组中。

    【讨论】:

      【解决方案4】:

      内存紧凑设计

      您的任务显然是针对一些2B-values 的内存轻量级占用。

      Python 中的解决方案还有一些需要考虑的因素。

      假设值的范围,满足在int-s 的2B-范围内表示的值范围(数字范围0..65535)具有内存效率只是一种错觉。

      您的设计应至少考虑与对象的“internal_representation”相关的开销 + 与对象实例的 相关的开销访问方法,以获得“那里”和“回来”的数字(不是说性能影响,因为您的要求集中在低内存占用,但更智能的是代理数据结构,更大的数据结构访问/维护 CPU 成本通常会增加)。

      如果您的主要动机是设计低内存占用空间,那么最坏的情况将总结所有这些静态内存分配 + 访问方法期间请求的任何动态分配的要求对象修改操作 + import-ed 模块的大小。

      一旦谈到 numpy - 一个很棒的工具 - 您将获得一个强大的库,用于快速、矢量化数组操作,并具有给定的单元数据表示 (dtype = numpy.uint8)。

      隐藏部分(对于代码设计低内存占用的任何假设)是考虑该方法的整体内存成本。

      不仅要比较对象大小,还要比较与类相关的开销(为清楚起见,没有显示大量 numpy 方法):

      >>> anIntOBJECT= 8
      >>> anIntOBJECT.__sizeof__()   # ____________________________instance-method works
      12
      >>> sys.getsizeof(anIntOBJECT) # kindly do not modify the MCVE with erroneous code
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      NameError: name 'sys' is not defined
      >>> dir(anIntOBJECT)
      ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
      >>> len( dir( anIntOBJECT ) )                  # Class-methods
      64
      

      另一种基于字符串的数据表示方法:

      >>> aStrOBJECT = "08"
      >>> aStrOBJECT.__sizeof__()    # ____________________________instance-method works
      23
      >>> sys.getsizeof(aStrOBJECT)  # kindly do not modify the MCVE with erroneous code
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      NameError: name 'sys' is not defined
      >>> dir( aStrOBJECT )
      ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
      >>> len( dir( aStrOBJECT ) )
      71
      

      可变序列的另一个主要原型:

      >>> aBytearrayOfINTs = bytearray()                                # in python base
      >>> aBytearrayOfINTs.__sizeof__() # _________________________instance-method works
      24
      >>> dir( aBytearrayOfINTs )
      ['__add__', '__alloc__', '__class__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'capitalize', 'center', 'count', 'decode', 'endswith', 'expandtabs', 'extend', 'find', 'fromhex', 'index', 'insert', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'pop', 'remove', 'replace', 'reverse', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
      >>> len( dir( aBytearrayOfINTs ) )
      76
      

      真正的数据结构实现:访问和维护方法决定

      在所有情况下,数据结构访问/维护方法将是一个决定性因素,可能不仅仅是单值(最小表示)内存占用量预期。

      【讨论】:

      • 我不知道原作者针对的是哪种架构,但在大多数情况下,基于类的成本相对于实例成本是可以忽略不计的。在大多数情况下,您的实例实际上比课程的成本要多得多。只有当你真正在微不足道的硬件上运行时(比如一些内存小于 1MB 的嵌入式系统),你才会关心导入模块或使用某些类的成本。还必须说,一旦您导入模块,您就有了 Python 中与类相关的开销——包含的所有类都将立即添加到内存中。
      • 是的,不幸的是 numpy uint8 仍然需要 12 个字节,所以我想唯一的出路是使用 cython...
      • 您需要存储多少个2B-s?每次调用 .put() / .get() [usec] 需要多快?
      • @RadioControlled,你看过我对你问题的回答吗?是的,一个 numpy uint8 仍然需要 12 个字节,因为添加了正常的对象开销。但是当您使用数组时,单个条目将仅使用类型所需的数量(uint8 为 1 个字节)。
      • @user3666197:你不应该直接调用像__sizeof__ 这样的方法。导入 sys 并使用 sys.getsizeof 是获取对象大小的正确方法。
      猜你喜欢
      • 2012-06-15
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多