使用NumPy时的数据类型大小

68
在NumPy中,我可以通过以下方式获取特定数据类型的大小(以字节为单位):
datatype(...).itemsize

或者:

datatype(...).nbytes

例如:

np.float32(5).itemsize # 4
np.float32(5).nbytes   # 4

我有两个问题。首先,有没有一种方法可以在不创建数据类型实例的情况下获取这些信息?其次,itemsizenbytes之间有什么区别?
3个回答

88
你需要一个 dtype 的实例来获取项目大小,但你不需要一个 ndarray 的实例。(就像下面将要清楚的那样,nbytes 是数组的属性,而不是 dtype 的属性。)
例如:
print np.dtype(float).itemsize
print np.dtype(np.float32).itemsize
print np.dtype('|S10').itemsize

itemsizenbytes 之间的区别而言,nbytes 只是 x.itemsize * x.size

例如:

In [16]: print np.arange(100).itemsize
8

In [17]: print np.arange(100).nbytes
800

1
好的答案。实际上,此时我并没有使用数组。在我的真实用例中,我有一个基于记录的数据文件格式——它有一个带有240个字节的头部,然后是数据。数据的大小由元素数量(从头部读取)确定,但数据类型未存储 :-(。最终,我希望用户能够传递 dtype=...,从而获取每个数据元素的大小,以便我可以知道数据的大小。这样,我就可以直接查找文件中的任何记录并读取它。看起来 np.dtype 是正确的选择...谢谢。 - mgilson
1
说实话,nbytes 作为数据类型的一个实例似乎有些令人困惑,因为它只在数组中特别有用... 当然,我想我对 numpy 数据模型的了解还不够深入,不能对此发表太多评论... 不管怎样,谢谢。这正是我需要的。 - mgilson
我同意,numpy的标量(例如np.float32(5))可能会令人困惑。numpy标量和0维numpy数组(例如np.array(5, dtype=np.float32))之间的区别更加令人困惑。(尝试对0维数组进行索引!)numpy标量存在并具有与普通ndarray相同的属性,这样像x[5].abs()这样的操作对于1d数组就能正确地工作。从“更广泛的角度”来看,这是有道理的,但它也会导致很多混淆。 - Joe Kington

17

查看NumPy C源代码文件,以下是注释:

size : int
    Number of elements in the array.
itemsize : int
    The memory use of each array element in bytes.
nbytes : int
    The total number of bytes required to store the array data,
    i.e., ``itemsize * size``.

因此,在NumPy中:

>>> x = np.zeros((3, 5, 2), dtype=np.float64)
>>> x.itemsize
8

因此,.nbytes是以下内容的快捷方式:

>>> np.prod(x.shape)*x.itemsize
240
>>> x.nbytes
240

因此,如果要获取NumPy数组的基本大小而不创建其实例,可以执行以下操作(假设为3x5x2的双精度数组):
>>> np.float64(1).itemsize * np.prod([3,5,2])
240

然而, NumPy 帮助文件中有一个重要的注释:

|  nbytes
|      Total bytes consumed by the elements of the array.
|
|      Notes
|      -----
|      Does not include memory consumed by non-element attributes of the
|      array object.

你通过 np.float64(1) 创建了一个实例,这正是我想要避免的。我想要避免它的原因是当读到那一行时,用户可能会问“为什么是1?”...而事实上,1并不特殊...只是我需要一个np.float64的实例来获取itemsize...然而,对于回答关于itemsize与nbytes(并阅读源代码)的第二个问题,加一分。 - mgilson
2
你也可以使用 np.float64().itemsize。然而,如果你计时这两种替代方法,np.dtype(np.float64).itemsizenp.float64().itemsize 稍微快一点。虽然差别不大,但足以影响选择。最终取决于你认为哪种更易读。 - dawg
有趣...感谢指出np.float64()也可以使用。 - mgilson

2
使用np.iinfo来处理整数,使用np.finfo来处理浮点数。然后,使用.bits属性,并除以8得到字节数。根据问题的要求,不需要创建数据类型的实例。
例如:
np.iinfo(np.int32).bits // 8      # 4  
np.finfo(np.float16).bits // 8    # 2

这是正确答案。 - Jason S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接