NEP 34 — 禁止从序列推断 dtype=object#
- 作者:
Matti Picus
- 状态:
最终
- 类型:
标准轨道
- 创建时间:
2019-10-10
- 解决时间:
https://mail.python.org/pipermail/numpy-discussion/2019-October/080200.html
摘要#
当用户使用序列的序列创建数组时,他们有时会因为嵌套序列的长度不匹配而出错,这通常称为“锯齿状数组”。在这里,我们将它们称为锯齿状嵌套序列。通过 `np.array([<ragged_nested_sequence>])` 创建此类数组,而不指定 `dtype` 关键字参数,目前将默认创建一个 `object` 类型的数组。将行为更改为引发 `ValueError`。
动机与范围#
用户在使用 `np.array` 创建 `numpy.ndarray` 时指定列表的列表,可能会错误地传入不同长度的列表。目前我们接受此输入并自动创建一个 `dtype=object` 的数组。这可能会令人困惑,因为它很少是期望的结果。将自动数据类型检测更改为从不为锯齿状嵌套序列(定义为序列的递归序列,其中同一级别的并非所有序列都具有相同的长度)返回 `object`,将强制用户显式指定他们确实希望创建 `object` 数组。请注意,`列表`、`元组` 和 `nd.ndarrays` 都是序列[0]。例如,请参阅问题 5303。
用法与影响#
在此更改后,使用锯齿状嵌套序列的数组创建必须显式定义 dtype
>>> np.array([[1, 2], [1]])
ValueError: cannot guess the desired dtype from the input
>>> np.array([[1, 2], [1]], dtype=object)
# succeeds, with no change from current behaviour
此弃用将影响任何内部调用 `np.asarray` 的调用。例如,`assert_equal` 系列函数调用 `np.asarray`,因此用户将不得不更改类似如下的代码
np.assert_equal(a, [[1, 2], 3])
改为
np.assert_equal(a, np.array([[1, 2], 3], dtype=object))
详细描述#
要显式设置对象数组的形状,因为有时很难确定所需的形状,可以这样做
>>> arr = np.empty(correct_shape, dtype=object)
>>> arr[...] = values
我们还将拒绝混合非序列和序列的序列,例如,所有这些都将被拒绝
>>> arr = np.array([np.arange(10), [10]])
>>> arr = np.array([[range(3), range(3), range(3)], [range(3), 0, 0]])
实现#
要更改的代码位于 `PyArray_GetArrayParamsFromObject` 和内部 `discover_dimensions` 函数中。在 `PR 14794` 中的第一个实现导致了许多下游库失败,并在 1.18 发布前被撤销。随后,下游库修复了他们使用锯齿状数组的地方。重新实现成为 `PR 15119`,并已为 1.19 版本合并。
向后兼容性#
任何依赖于从锯齿状嵌套序列创建对象数组的程序都需要修改其代码。在弃用期间,当前行为将发出 `DeprecationWarning`。
替代方案#
我们可以继续当前的情况。
还有人建议向数组创建添加一个 `depth` 参数,或者添加另一个数组创建 API 函数 `ragged_array_object`。目的是消除从 `array([[1, 2], [1]], dtype=object)` 创建对象数组时的歧义:返回的数组的形状应该是 `(1,)` 还是 `(2,)`?此 NEP 不处理此问题,仅弃用在未指定 `dtype=object` 的情况下使用 `array` 来处理锯齿状嵌套序列。锯齿状嵌套序列的用户将来可能会面临另一个弃用周期。理由:我们认为很少有用户打算这样使用锯齿状数组,这从来都不是 NumPy 数组的预期用途。用户可能最好使用其他库或直接使用列表的列表。
还有人建议弃用所有自动创建 `object` 类型数组的行为,这将需要为类似 `np.array([Decimal(10), Decimal(10)])` 的情况添加显式的 `dtype=object`。这也超出了当前 NEP 的范围。理由:评估这个更大范围更改的影响更难,我们不确定有多少用户会受到影响。
讨论#
来自问题 5303 的评论表明,早在 2014 年,这种行为就是非预期的。在接下来的几年里,曾有人建议进行更改,但没有一项成功。`PR 14794` 中的 WIP 实现似乎指向了该方法的有效性。
参考文献和脚注#
版权#
本文档已置于公共领域。