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-dtype 数组。更改行为,改为引发 ValueError

动机和范围#

通过 np.array 使用列表的列表创建 numpy.ndarray 的用户可能会错误地传入长度不同的列表。目前,我们接受此输入并自动创建一个 dtype=object 的数组。这可能会令人困惑,因为它很少是想要的。将自动 dtype 检测更改为从不为参差不齐的嵌套序列(定义为序列的递归序列,其中同一级别的序列长度不相同)返回 object 将强制实际上希望创建 object 数组的用户显式指定它。请注意,liststuplesnd.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

替代方案#

  • 我们可以继续目前的状况。

  • 还建议向数组创建添加一个 kwarg depth,或者可能添加另一个数组创建 API 函数 ragged_array_object。目标是消除从 array([[1, 2], [1]], dtype=object) 创建对象数组时的歧义:返回的数组的形状应该是 (1,) 还是 (2,)?此 NEP 没有处理该问题,仅弃用在没有 dtype=object 的情况下使用 array 用于参差不齐的嵌套序列。参差不齐嵌套序列的用户将来可能面临另一个弃用周期。基本原理:我们预计使用这种参差不齐数组的用户非常少,这从未被认为是 NumPy 数组的用例。用户很可能更好地使用另一个库或仅使用列表的列表。

  • 还建议弃用所有自动创建 object-dtype 数组,这将需要为类似 np.array([Decimal(10), Decimal(10)]) 的内容添加显式的 dtype=object。这也超出了当前 NEP 的范围。基本原理:评估此更大更改的影响更难,我们不确定这可能会影响多少用户。

讨论#

问题 5303 的评论表明,早在 2014 年,这就被认为是意外行为。在随后的几年里,人们提出了更改它的建议,但没有一个成功。 PR 14794 中的 WIP 实现似乎指出了这种方法的可行性。

参考文献和脚注#