NEP 34 — 禁止从序列推断 dtype=object
#
- 作者:
Matti Picus
- 状态:
最终
- 类型:
标准跟踪
- 创建日期:
2019-10-10
- 决议:
https://mail.python.org/pipermail/numpy-discussion/2019-October/080200.html
摘要#
当用户使用序列的序列创建数组时,有时会错误地匹配嵌套序列的长度,这通常被称为“不规则数组”(ragged arrays)。在此,我们将其称为不规则嵌套序列。目前,通过不带 dtype
关键字参数的 np.array([<ragged_nested_sequence>])
创建此类数组,会默认生成一个 object
-dtype 数组。本提案旨在将此行为更改为引发 ValueError
异常。
动机与范围#
用户通过 np.array
创建 numpy.ndarray 时,如果指定列表的列表(lists-of-lists),可能会错误地传入长度不同的列表。目前,我们接受这种输入并自动创建一个 dtype=object
的数组。这可能令人困惑,因为这很少是用户所期望的结果。将自动 dtype 检测更改为对于不规则嵌套序列(定义为递归的序列的序列,其中同一层的所有序列长度不都相同)不再返回 object
,将迫使那些确实希望创建 object
数组的用户明确指定。请注意,lists
、tuples
和 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,该 PR 已合并到 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(进行中)实现似乎指明了这种方法的可行性。
参考文献和脚注#
版权#
本文档已进入公共领域。