为什么numpy允许混合数据类型,但文档却说它不行。

4

我有一个普遍性的问题,但没有人能够给我答案。我在Python官方文档和其他来源(如bootcamp和datacamp)中进行了大量搜索。

问题是,我在所有地方都看到numpy不支持异构数据类型(官方文档

但是,当我写下面的代码时,它可以正常工作。那么,如果numpy不支持异构数据类型,为什么编码允许呢?

import numpy as np

x = np.array(["hello", 3, 4, 5])

print(a)

上述语句成功执行。


你有文档链接吗?上面写明它不支持异构数据类型? - RvdV
1
当我尝试运行你问的那段代码时,数字被转换成了字符串。因此,所创建的数组实例的数据类型是同质的。 - yann ziselman
这里有一个单一的数据类型,'<U5' - juanpa.arrivillaga
@RvdV请看这里,第二个要点表明它不支持同种数据类型。 https://numpy.org/devdocs/user/whatisnumpy.html - Jahanzaib Niazi
@juanpa.arrivillaga 是的,我知道它确实可以,你的解释非常好!我只是认为为了完整地回答问题,将其链接起来会很好。 - RvdV
显示剩余3条评论
2个回答

2

我试过了,实际上它是均匀的!看看这个:

>>> np.array(["hello", 1, 2, 3])
  array(['hello', '1', '2', '3'], dtype='<U5')

我们在这里看到的类型是Unicode (https://numpy.org/devdocs/reference/generated/numpy.dtype.kind.html#numpy.dtype.kind),具体而言是U类型,长度为5或更少。因此所有整数都被转换为unicode /字符串类型,从而使数组变得同质化!

尝试强制转换为int将会抛出错误:

np.array(["hello", 1, 2, 3], dtype=np.int)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  ValueError: invalid literal for int() with base 10: 'hello'

先生,您的意思是默认情况下numpy将所有内容都视为Unicode吗?我理解得对吗? - Jahanzaib Niazi
1
它将尝试强制转换数据为一种容纳所有数据的类型,这种情况下是字符串。x = np.array(['hello', 1, 2, 3, float]) 将是 object 数据类型,并且它可能会为每个元素存储对 Python 对象的引用或类似的东西。您可以使用 sys.getsizeof 查看所有这些不同数组占用的空间量。 - Reti43
我不确定,但我认为它会尝试找到最具体的数据类型来适应所有输入。如果列表中只有整数,则为整数,但由于列表中有字符串,因此它会回退到字符串,因为它可以将整数转换为字符串,但反之则不行。 - RvdV

2
一个numpy数组有一个已声明的类型(dtype)。数组中的所有元素都必须符合该类型或强制转换为它。就这样。
简单地说,某些类型更加“宽容”:如果您使用浮点类型,则大多数整数值(除了最大的那些)将轻松存储,而反之则是错误的。或者您甚至可以使用一个object dtype,它允许您存储任何Python值,包括列表或字典。
arr = np.array((1, 2.5, 'foo'), dtype=object)
print(type(arr[0]), type(arr[1]), type(arr[2]))

提供:

<class 'int'> <class 'float'> <class 'str'>

缺点在于在这里使用numpy数组没有意义,因为您将无法对其进行矢量化操作...
在@juanpa.arrivillaga的精彩评论之后,我将尝试更进一步地解释numpy中发生的事情。numpy通常存储原始数据,以便它们可以直接被C例程使用,高速处理(在numpy语言中称为矢量化)。 dtype属性是由ndarray的所有元素共同构建的,并且通常是数值(C)类型。例如,numpy数组将轻松存储和处理固定大小的整数(int32或int64)。在这种情况下,数组中的每个插槽将将数字存储为4(resp 8)字节整数,而python整数是多精度数字。
使用对象dtype时会发生什么是,数组实际上将包含对任何python对象的引用(将其视为地址)。

2
严谨地说,数组实际上并不存储 Python 对象。dtype=object 基本意味着“指向 CPython 对象的引用(指针)”。而且你必须小心处理 type(arr[i]),因为它将返回装箱类型。当然,所有 Python 对象都是这样工作的,因为一切都是“对象的引用”...但是,在思考 NumPy 时,这里存在微妙之处。 - juanpa.arrivillaga
先生,您的意思是numpy默认具有dtype吗? - Jahanzaib Niazi
@JahanzaibNiazi 这就是文档所述的,正如你在问题中指出的那样,numpy数组是同质的。 - juanpa.arrivillaga
非常感谢您!现在我明白了您的意思。 - Jahanzaib Niazi
非常感谢您提供这么详细的解释。致意! - Jahanzaib Niazi
显示剩余3条评论

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