NEP 34 — 禁止dtype=object从序列推断#

作者

马蒂·皮库斯

地位

最终的

类型

标准轨道

创建

2019-10-10

解决

https://mail.python.org/pipermail/numpy-discussion/2019-October/080200.html

抽象的

当用户使用序列序列创建数组时,他们有时会在匹配嵌套序列的长度时出错,通常称为“不规则数组”。在这里,我们将它们称为不规则嵌套序列。现在,通过np.array([<ragged_nested_sequence>])不带关键字参数创建此类数组dtype将默认为object-dtype 数组。改变行为来提高 a ValueError

动机和范围#

通过 创建numpy.ndarray时指定列表列表的用户np.array可能会错误地传入不同长度的列表。目前我们接受此输入并自动创建一个带有 的数组dtype=object。这可能会令人困惑,因为这很少是我们所期望的。将自动数据类型检测更改为从不返回object参差不齐的嵌套序列(定义为序列的递归序列,其中并非同一级别上的所有序列都具有相同的长度)将迫使实际希望创建 object数组的用户显式指定这一点。请注意lists, 、tuples、 和nd.ndarrays都是序列[ 0 ]。例如,请参见问题 5303

使用和影响#

进行此更改后,使用不规则嵌套序列创建数组必须显式定义数据类型:

>>> 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在数组创建中添加 kwarg,或者添加另一个数组创建 API 函数ragged_array_object。目标是消除创建对象数组时的歧义:返回的数组应该具有, 或的形状 ?此 NEP 不处理该问题,并且仅反对对参差不齐的嵌套序列使用with no 。不规则嵌套序列的用户将来可能会面临另一个弃用周期。理由:我们预计很少有用户打算使用这样的不规则数组,这从来都不是 NumPy 数组的用例。用户可能更适合使用另一个库或仅使用列表列表。array([[1, 2], [1]], dtype=object)(1,)(2,)arraydtype=object

  • 还建议弃用所有自动创建object-dtype 数组,这需要dtype=object为.这也超出了当前新经济政策的范围。理由:很难评估这一较大变化的影响,我们不确定这可能会影响多少用户。np.array([Decimal(10), Decimal(10)])

讨论

对问题 5303的评论表明,早在 2014 年,这就是无意的行为。在随后的几年中,已经提出了更改它的建议,但没有一个得到落实。PR 14794中的 WIP 实施似乎表明了这种方法的可行性。

参考文献和脚注#