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 陣列的使用者明確指定該 dtype。請注意,liststuplesnd.ndarrays 都是序列 [0]。例如,請參閱 issue 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 的範圍。理由:更難評估此較大變更的影響,我們不確定這可能會影響多少使用者。

討論#

issue 5303 的評論指出,早在 2014 年,這就是非預期的行為。隨後幾年提出了變更它的建議,但沒有任何建議被採納。PR 14794 中的 WIP 實作似乎指向此方法的可行性。

參考資料和註腳#