NEP 56 — NumPy 主要命名空間中的陣列 API 標準支援#

作者:

Ralf Gommers <ralf.gommers@gmail.com>

作者:

Mateusz Sokół <msokol@quansight.com>

作者:

Nathan Goldbaum <ngoldbaum@quansight.com>

狀態:

最終

取代:

NEP 30 — NumPy 陣列的鴨子型別 - 實作NEP 31 — NumPy API 的內容區域與全域覆寫NEP 37 — 類似 NumPy 模組的調度協定NEP 47 — 採用陣列 API 標準

型別:

標準追蹤

建立日期:

2023-12-19

決議:

https://mail.python.org/archives/list/numpy-discussion@python.org/message/Z6AA5CL47NHBNEPTFWYOTSUVSRDGHYPN/

摘要#

本 NEP 提議在 NumPy 的主要命名空間中,為 2.0 版本新增幾乎完整支援 2022.12 版本的陣列 API 標準。

在主要命名空間中採用具有許多優點;對於依賴 NumPy 並希望開始支援其他陣列程式庫的程式庫而言,這尤其重要。SciPy 和 scikit-learn 是兩個已經朝著這個方向發展的著名程式庫。在主要命名空間中支援陣列 API 標準的需求,來自這些程式庫以及使用不同陣列物件的實驗性 numpy.array_api 實作所汲取的經驗。對於其他陣列程式庫、像 Numba 這樣的 JIT 編譯器,以及可能更容易在不同陣列程式庫之間切換的終端使用者來說,也將帶來好處。

動機與範疇#

注意

本 NEP 中提議的主要變更已在 2023 年 4 月的 NumPy 2.0 開發人員會議上提出 (請參閱此處的會議簡報),並在那裡獲得了贊同。NumPy 2.0 的大部分實作工作已經合併。對於其餘部分,PR 已準備就緒 - 這些主要是特定於陣列 API 支援的項目,如果沒有該背景,我們可能不會考慮將其包含在 NumPy 中。本 NEP 將更詳細地關注這些 API 和 PR。

NEP 47 — 採用陣列 API 標準 包含將陣列 API 支援新增至 NumPy 的動機。本 NEP 擴展並取代了 NEP 47。NEP 47 旨在建立單獨的 numpy.array_api 子模組而不是主要命名空間的主要原因是,轉型規則差異太大。隨著基於數值的轉型被移除 (NEP 50 — Python 純量值的提升規則),這將在 NumPy 2.0 中解決。讓 NumPy 成為陣列 API 標準的超集合,將顯著改善程式碼的可移植性,使其能移植到其他程式庫 (CuPy、JAX、PyTorch 等),從而解決 2020 年 NumPy 使用者調查中最受使用者歡迎的請求之一[4] (GPU 支援)。請參閱 numpy.array_api API 文件 (1.26.x),以概述其與主要命名空間之間的差異 (請注意,「嚴格性」的那些不適用)。

使用 numpy.array_api (仍標記為實驗性) 的經驗表明,單獨的嚴格實作和單獨的陣列物件主要適用於測試目的,但不適用於下游程式庫中的常規使用。在主要命名空間中提供支援可以解決此問題。因此,本 NEP 取代了 NEP 47。numpy.array_api 模組將移至獨立套件,以便於進行不與 NumPy 發布週期綁定的更輕鬆更新。

陣列 API 標準中的一些關鍵設計規則 (例如,從輸入 dtype 可預測輸出 dtype、沒有由關鍵字控制的不同回傳數量的多型 API) 也將應用於不屬於陣列 API 標準的 NumPy 函數,因為現在人們理解這些設計規則通常是良好的實務。尤其是這兩個設計規則,使 Numba 和其他 JIT 編譯器更容易支援 NumPy 或與 NumPy 相容的 API。我們將注意到,將現有引數設為僅限位置和僅限關鍵字對於未來新增到 NumPy 的函數來說是個好主意,但不會對現有函數執行,因為每個此類變更都是向後相容性中斷,而且對於編寫可在支援標準的程式庫之間移植的程式碼來說,這不是必要的。現在將這些設計規則應用於主要命名空間中的所有函數的另一個原因是,這樣可以更容易地處理 NumPy 中已存在的潛在新函數的標準化 - 否則,由於需要向後相容性,這些函數可能會被封鎖或被迫使用替代函數名稱。

重要的是,新增至主要命名空間的新函數與 NumPy 的其餘部分良好整合。因此,例如,它們應遵循廣播和其他預期規則,並適用於所有 NumPy 的 dtypes,而不僅僅是標準中的那些。向後不相容的變更也是如此 (例如,線性代數函數需要以相同的方式支援批次處理,並將最後兩個軸視為矩陣)。因此,NumPy 應該變得更加一致,而不是更不一致。

以下是我們認為整套擬議變更的主要預期優點和成本

優點

  • 它將使陣列消耗程式庫 (例如 SciPy 和 scikit-learn,以及堆疊中較小的較高層程式庫) 能夠實作對多個陣列程式庫的支援,

  • 它將消除其他陣列程式庫在選擇要實作的 API 時,必須在「NumPy API 和陣列 API 標準之間做出選擇」的問題,

  • 透過提供更明確定義且最小的 API 目標介面,以及透過解決由 Numpy 語意引起的一些差異 (這些語意在 JIT 編譯器中難以支援),使 CuPy、JAX、PyTorch、Dask、Numba 和其他此類程式庫和編譯器更容易匹配或支援 NumPy,

  • 一些獨立於標準的新功能:新增 matrix_transposendarray.mT、新增 vecdot、引入 matrix_norm/vector_norm (它們可以製成 gufuncs,vecdot 已經有一個 PR 使其成為 gufunc),

  • NumPy 和其他陣列程式庫的 API 之間更緊密的對應關係,將降低終端使用者在從一個陣列程式庫切換到另一個陣列程式庫時的學習曲線,

  • 陣列 API 標準往往比 NumPy 本身具有更一致的行為 (在兩者之間存在差異的情況下,請參閱標準中的線性代數設計原則資料相關的輸出形狀頁面),

成本

  • 許多向後相容性中斷 (大多數是次要的,請參閱下方的向後相容性章節),

  • 使用約 ~20 個別名擴展主要命名空間的大小 (例如,具有 C99 名稱的 acos & co. 別名 arccos & co.)。

總體而言,我們相信優點遠遠超過成本 - 並且是永久性的,而成本在很大程度上是暫時性的。尤其是,對於希望實現與 NumPy 相容性的陣列程式庫和編譯器而言,好處是顯著的。因此,對於 PyData (或科學 Python) 生態系統整體而言,長期好處也是顯著的 - 因為下游程式庫能夠更輕鬆地支援多個陣列程式庫。所需的重大變更數量相當有限,而且這些變更的影響似乎不大。並非沒有痛苦,但我們相信其影響小於 NumPy 2.0 中其他重大變更的影響,而且是值得付出的代價。

本 NEP 的範疇包括

  • 在主要命名空間以及 numpy.linalgnumpy.fft 中,支援 2022.12 版本陣列 API 標準所需的 NumPy Python API 變更,

  • 為了與標準的關鍵設計原則保持一致,現有 NumPy 函數 (尚未或未包含在陣列 API 標準中) 行為的變更。

本 NEP 的範疇不包括

  • 與陣列 API 標準無關的 NumPy Python API 的其他變更,

  • NumPy C API 的變更。

本 NEP 將取代以下 NEP

使用方式與影響#

我們心中有幾種不同的使用者類型:編寫數值程式碼的終端使用者、依賴 NumPy 並希望開始支援多個陣列程式庫的下游套件,以及旨在實作類似 NumPy 或與 NumPy 相容的 API 的其他陣列程式庫和工具。

可能會從陣列 API 支援中受益的最主要使用者可能是希望開始支援 CuPy、PyTorch、JAX、Dask 或其他此類程式庫的下游程式庫。SciPy 和 scikit-learn 已經在執行此操作的道路上走了很遠,並在其自身 API 的一小部分中成功支援 CuPy 陣列和 PyTorch 張量 (該支援仍標記為實驗性)。

他們使用的主要原則是,他們將常規的 import numpy as np 替換為從輸入陣列檢索陣列程式庫命名空間的實用函數。他們將其稱為 xp,如果輸入是 NumPy 陣列,則它實際上是 np 的別名,對於 CuPy 陣列是 cupy,對於 PyTorch 張量是 torch。然後,此 xp 允許編寫適用於所有這些程式庫的程式碼 - 因為陣列 API 標準是共同點。作為一個具體範例,此程式碼取自 scipy.cluster

def vq_py(obs, code_book, check_finite=True):
    """Python version of vq algorithm"""
    xp = array_namespace(obs, code_book)
    obs = as_xparray(obs, xp=xp, check_finite=check_finite)
    code_book = as_xparray(code_book, xp=xp, check_finite=check_finite)

    if obs.ndim != code_book.ndim:
        raise ValueError("Observation and code_book should have the same rank")

    if obs.ndim == 1:
        obs = obs[:, xp.newaxis]
        code_book = code_book[:, xp.newaxis]

    # Once `cdist` has array API support, this `xp.asarray` call can be removed
    dist = xp.asarray(cdist(obs, code_book))
    code = xp.argmin(dist, axis=1)
    min_dist = xp.min(dist, axis=1)
    return code, min_dist

它看起來很像普通的 NumPy 程式碼,但將與例如 PyTorch 張量作為輸入一起執行,然後傳回 PyTorch 張量。當然,這個故事還有很多,而不僅僅是這個基本範例。關於 scikit-learn [1] 和 SciPy 的 [2] 經驗與影響 (在某些情況下效能大幅提升 - 使用 GPU 上的 PyTorch 與 NumPy 相比,LinearDiscriminantAnalysis.fit 顯示 ~28 倍的增益) 的這些部落格文章描繪了更完整的圖景。

對於直接使用 NumPy 的終端使用者來說,除了 NumPy 和他們可能也想使用的其他程式庫之間的差異減少之外,幾乎沒有變化。這縮短了他們的學習曲線,並使他們更容易在 NumPy 和 PyTorch/JAX/CuPy 之間切換。此外,他們應該受益於開始支援多個陣列程式庫的陣列消耗程式庫,使其使用 Python 套件堆疊進行科學計算或資料科學的體驗更加無縫。

最後,對於其他陣列程式庫的作者以及像 Numba 這樣的工具,使 NumPy 與陣列 API 標準對齊的 API 改善也將為他們節省時間。設計規則 ([3]),以及在某些情況下像 unique_* 這樣的新 API,由於更可預測的行為,因此更容易在 GPU 上和為 JIT 編譯器實作。

向後相容性#

具有向後相容性影響的變更分為以下幾類

  1. 在某些 NumPy 現在允許更彈性行為的地方,為了保持一致性/嚴格性而引發錯誤,

  2. 某些元素級函數和歸約的回傳陣列的 Dtypes,

  3. 少數容錯關鍵字的數值行為,

  4. 移至 numpy.linalg 並支援堆疊/批次處理的函數,

  5. asarrayarraycopy 關鍵字的語意,

  6. numpy.fft 功能的變更。

為了保持一致性/嚴格性而引發錯誤包括:

  1. 使 .T 對於 >2 維度產生錯誤,

  2. 使 cross 對於大小為 2 的向量產生錯誤 (僅支援大小為 3 的向量),

  3. 使 solve 對於不明確的輸入產生錯誤 (如果 x2.ndim == 1,則僅接受 x2 作為向量),

  4. outer 對於 >1-D 輸入引發錯誤而不是展平,

我們預期此類變更的影響很小。

某些元素級函數和歸約的回傳陣列的 Dtypes 包括需要保留 dtypes 的函數:如果輸入具有整數 dtype,則 ceilfloortrunc 將開始傳回具有相同整數 dtypes 的陣列。

我們預期此類變更的影響很小。

數值行為的變更 包括

  • pinvrtol 預設值從 1e-15 變更為依賴 dtype 的預設值 None,解釋為 max(M, N) * finfo(result_dtype).eps

  • matrix_ranktol 關鍵字變更為 rtol,但具有不同的解釋。此外,matrix_rank 將不再支援 1-D 陣列輸入,

對於這些容錯變更,發出 FutureWarning 似乎不合理;對於絕大多數使用者來說,它們將是虛假的警告,並且會迫使使用者硬式編碼容錯值以避免警告。數值結果的變更原則上是不受歡迎的,因此雖然我們預期影響很小,但在主要版本中執行此操作會很好。

我們預期此類變更的影響為中等。這是唯一一類不會導致明確例外或警告的變更,因此如果確實重要 (例如,下游測試開始失敗或使用者注意到行為變更),則可能需要使用者付出更多努力來追蹤問題。這種情況應該很少發生 - 在實作此變更的 PR 合併後一個月 (請參閱 gh-25437),迄今為止報告的影響是 AstroPy 中的單一測試失敗。

移至 numpy.linalg 並支援堆疊/批次處理的函數diagonaltrace 函數。它們是標準中 linalg 子模組的一部分,而不是主要命名空間。因此,它們將在 numpy.linalg 中引入。它們將對最後兩個軸而不是前兩個軸進行運算。這樣做是為了保持一致性,因為這現在是其他 NumPy 函數的工作方式,並支援「堆疊」(或其他程式庫中更常用的術語「批次處理」)。因此,同名的 linalg 和主要命名空間函數將有所不同。這在技術上並非重大變更,但由於同名函數的不同行為,可能會造成混淆。我們可能會棄用 np.tracenp.diagonal 來解決此問題,但最好不要立即棄用,以避免使用者必須編寫 if-2.0-else 條件程式碼。

我們預期此類變更的影響很小。

asarray 和 array 中 copy 關鍵字的語意 對於 copy=False 將從「如果需要則複製」變更為「永不複製」。現在有三種類型的行為而不是兩種 - copy=None 表示「如果需要則複製」。

我們預期此類變更的影響為中等。如果使用者因為在複製中明確使用 copy=False 而收到例外,但之前無論如何都已進行複製,則他們必須檢查其程式碼,並確定程式碼的意圖是舊的還是新的語意 (兩者似乎大致相同),並適當調整程式碼。我們預期大多數情況都是 np.array(..., copy=False),因為直到幾年前,它都比 np.asarray(...) 具有更低的額外負擔。但這已解決,並且 np.asarray(...) 是慣用的 NumPy 用法。

numpy.fft 的變更numpy.fft 子模組中的所有函數都需要為 32 位元輸入 dtypes 保留精度,而不是向上轉換為 float64/complex128。這是一個理想的變更,與 NumPy 作為一個整體的設計一致 - 但來自此模組中函數呼叫的回傳陣列的較低精度或 dtype 可能會影響使用者。此變更是透過基於新 gufunc 的實作以及在 (gh-25711) 中供應商提供的 C++ 版本 PocketFFT 進行的。

numpy.fft 的一個較小的向後不相容變更,是透過不允許 s 中的 None 值,並要求如果使用 s,則也必須指定 axes (請參閱 gh-25495),使 n-D 轉換中 saxes 引數的行為更容易理解。

我們預期此類變更的影響很小。

適應變更 & 工具支援#

陣列 API 的某些部分已作為 NumPy 2.0 的一般 Python API 清理的一部分實作 (請參閱 NEP 52),例如

  • 建立一種命名 infnan 的方法,該方法與陣列 API 相容。

  • 移除加密的 dtype 名稱,並為每個 dtype 建立 (與陣列 API 相容的) 標準名稱。

遷移到與 NEP 52 相容的程式碼庫的所有說明,都可在 NumPy 2.0 遷移指南 中找到。

此外,還為 Python API 變更的自動遷移實作了新的 ruff 規則。值得指出的是,新的規則 NP201 僅適用於遵守 NEP 52 變更,不涵蓋使用屬於陣列 API 標準的新函數,也不涵蓋具有上述某些類型向後不相容變更的 API。

為了自動遷移到與陣列 API 相容的程式碼庫,正在實作新的規則 (請參閱問題 ruff#8615 和 PR ruff#8910)。

有了這兩項規則,下游使用者應該能夠更新他們的專案,在自動化可行的範圍內,更新到一個與函式庫無關的程式碼庫,使其能夠受益於不同的陣列函式庫和裝置。

無法自動處理的向後不相容變更(例如,線性代數函數的 rtol 預設值變更)將會以與 NumPy 2.0 中任何其他向後不相容變更相同的方式處理 - 透過文件、發行說明、API 遷移以及在數個版本中逐步棄用。

詳細描述#

在本節中,我們將重點關注特定的 API 新增功能和特性,如果標準不存在,且我們不必思考/擔心其主要目標(編寫可跨多個陣列函式庫及其支援的功能(如 GPU 和其他硬體加速器或 JIT 編譯器)移植的程式碼),我們將不會考慮將其引入 NumPy。

device 支援#

裝置支援可能是最明顯的例子。NumPy 現在是且將會繼續是一個僅限 CPU 的函式庫,那麼為什麼還要費心引入 ndarray.device 屬性或在多個函數中使用 device= 關鍵字呢?這個功能純粹是為了更容易編寫可跨函式庫移植的程式碼。.device 屬性將返回一個代表 CPU 的物件,並且該物件將被接受作為 device= 關鍵字的輸入。例如

# Should work when `xp` is `np` and `x1` a numpy array
x2 = xp.asarray([0, 1, 2, 3], dtype=xp.float64, device=x1.device)

這將在 NumPy 中如預期般運作,從輸入列表建立一個 1 維 numpy 陣列。它也將適用於 CuPy 等,在這些函式庫中,它可能會在 GPU 或其他支援的裝置上建立一個新陣列。

isdtype#

陣列 API 標準引入了一個新的函數 isdtype 用於 dtype 的內省,因為 NumPy 中沒有合適的替代方案。最接近的是 np.issubdtype,然而,這假設了一個複雜的類別層次結構,而其他陣列函式庫沒有這種結構,而且 API 不是最符合人體工學的,並且需要更大的 API 介面(np.floating 和類似的)。isdtype 將成為內省 dtype 的新的標準方式。它對 dtype 的所有要求是,當與來自相同函式庫的其他 dtype 比較時,__eq__ 已實作且具有預期的行為。

請注意,作為 NEP 52 工作的一部分,一些 dtype 別名已被移除,並且標準的 Python 和 C 名稱已被記錄在文件中。另請參閱 gh-17325,其中涵蓋了 NumPy 在此方面缺乏良好 API 的問題。

copy 關鍵字語意#

asarrayarray 中的 copy 關鍵字現在將支援 True/False/None,並具有新的含義

  • True - 總是建立副本。

  • False - 永遠不建立副本。如果需要副本,則會引發 ValueError

  • None - 僅在必要時建立副本(先前為 False)。

astype 中的 copy 關鍵字將保持其目前的含義,因為當要求轉換為不同的 dtype 時,「永不複製」不太合理。

語意變更仍然存在一個小問題:如果對於使用者程式碼 np.array(obj, copy=False),NumPy 可能最終呼叫 obj.__array__,在這種情況下,將結果轉換為 NumPy 陣列是 obj.__array__ 的實作者的責任。因此,我們還需要在 __array__ 中新增一個 copy=None 關鍵字,並傳遞 copy 關鍵字值 - 注意不要在 __array__ 的實作者尚未擁有新關鍵字時破壞向後相容性(在這種情況下將發出 DeprecationWarning,以便逐步過渡)。

新的函數名稱別名#

在 NumPy 2.0 的 Python API 清理工作中(請參閱 NEP 52 — NumPy 2.0 的 Python API 清理),我們花費了大量精力來移除別名。因此,引入新的別名必須有充分的理由。在這種情況下,需要它才能與其他函式庫匹配。新增的主要別名集是用於三角函數,其中陣列 API 標準選擇遵循 C99 和其他函式庫,使用 acosasin 等,而不是 arccosarcsin 等。NumPy 通常也遵循 C99;目前尚不完全清楚為什麼多年前做出這個命名選擇。

總共在主命名空間中新增了 13 個別名,在 numpy.linalg 中新增了 2 個別名

  • 三角函數:acosacoshasinasinhatanatanhatan2

  • 位元運算函數:bitwise_left_shiftbitwise_invertbitwise_right_shift

  • 其他函數:concatpermute_dimspow

  • numpy.linalg 中:tensordotmatmul

未來,NumPy 可以選擇從其 __dir__ 中隱藏原始名稱,以引導使用者使用每個函數的首選拼寫。

具有重疊語意的新關鍵字#

與函數名稱別名類似,有一些新的關鍵字與現有的關鍵字重疊

  • stdvarcorrection 關鍵字(與 ddof 重疊)

  • sortargsortstable 關鍵字(與 kind 重疊)

correction 名稱是為了清晰起見(「自由度差值」不容易理解)。stablekind 的補充,kind 已經有 'stable' 作為一個選項(儘管單獨的關鍵字可能更容易被發現,因此仍然很高興擁有),允許函式庫保留更改/改進穩定和不穩定排序演算法的權利。

新的 unique_* 函數#

unique 函數,其具有影響傳回元組基數的 return_indexreturn_inversereturn_counts 參數,在陣列 API 中被四個各自的函數取代:unique_allunique_countsunique_inverseunique_values。這些新函數避免了多型性,多型性往往是 JIT 編譯器和靜態型別的問題。因此,使用這些函數有助於像 Numba 這樣的工具,以及像 Mypy 這樣的靜態型別檢查器的使用者。

np.bool 新增功能#

曾經存在於 NumPy 中但被移除的別名之一是 np.bool。為了符合陣列 API,它以不同的含義重新引入,因為現在它指向 NumPy 的 bool 而不是 Python 內建的 bool。這個變更是一個好主意,我們本來就計劃進行此變更,因為 boolbool_ 更容易理解。但是,如果它不是陣列 API 標準的一部分,我們可能不會將該名稱的重新引入安排在 2.0 版本中。

未採納的標準部分#

標準規定了一些我們建議遵循的事項(至少目前是這樣)。這些是

  1. 要求 sumproddtype=None 時始終將較低精度的浮點 dtype 向上轉換為 float64

    理由:這可能具有破壞性(例如, float32_arr - float32_arr.mean() 將產生一個 float64 陣列,並使記憶體使用量增加一倍)。雖然對於具有較低精度整數 dtype 的輸入已經進行了這種向上轉換,並且似乎有助於防止溢位,但對於浮點 dtype 而言,要求這樣做似乎不太合理。

    array-api#731 已開啟以重新考慮標準中的這個設計選擇,並且該選擇已被下一個標準版本接受。

  2. 在許多地方使函數簽名僅為位置參數和僅為關鍵字參數。

    理由:2022.12 版本的標準說「必須」,但這在即將發布的 2023.12 版本中已經軟化為「應該」,以承認不這樣做是可以的 - 畢竟,陣列函式庫的使用者仍然可以使用推薦的樣式編寫他們的程式碼。對於 NumPy 來說,這些變更將會很有用,並且似乎我們可能會隨著時間的推移引入許多或所有這些變更(事實上,ufuncs 已經符合標準),但是沒有必要倉促進行此變更 - 為 2.0 這樣做將是不必要的破壞性。

  3. 「就地運算必須具有與其各自的二元運算(即,兩個運算元、非賦值)運算相同的行為(包括特殊情況)」(排除對視圖的影響)的要求。

    理由:這個要求非常合理,並且可能是大多數 NumPy 使用者所期望的行為。但是,棄用就地運算子的不安全轉換是一個很難預測其影響的變更。因此,這需要首先進行調查,然後如果影響足夠小,則可以根據 NumPy 的正常向後相容性指南棄用目前的行為。

    此主題在 gh-25621 中追蹤。

注意

我們注意到,仍然存在一種 NumPy 特有的行為,即在大多數標準和其他陣列函式庫傳回 0 維陣列的情況下,傳回陣列純量而不是 0 維陣列(例如,索引和歸約)。陣列純量基本上是鴨子型別的 0 維陣列,這是標準允許的(它不強制規定只有一種陣列類型,也不包含 isinstance 檢查或其他語意,這些語意不適用於陣列純量)。在過去一年中,已經進行了多次關於從 NumPy 中移除陣列純量,或至少不再預設傳回它們的可行性的討論。然而,這將是一項巨大的努力,並且存在一些關於技術風險和變更影響的不確定性,而且沒有人承擔下來。鑑於陣列純量實作了一個很大程度上與陣列相容的介面,這似乎不是關於陣列 API 標準相容性(或一般而言)的最高優先事項。

實作#

陣列 API 標準支援的追蹤問題(gh-25076)記錄了實作完整支援的進度,並連結到相關的討論。它列出了所有驗證或提供陣列 API 支援的相關 PR(已合併和待處理)。

由於 NEP 52 在某種程度上與此 NEP 混合在一起,我們也可以在其追蹤問題(gh-23999)上找到一些相關的實作和討論。

作為第一個合併的 PR 之一,包含了一個新的 CI 任務,該任務新增了 array-api-tests 測試套件。這樣,我們可以更好地控制每次新增的函數/別名批次,並可以確保實作符合陣列 API 標準(請參閱 gh-25167)。

然後,我們繼續一次合併一個批次,新增特定的 API 區段。下面我們列出了一些更重要的區段,包括我們在本 NEP 前幾節中討論過的一些區段

替代方案#

在 NumPy 的主命名空間中實作陣列 API 標準支援的替代方案包括

  • 一個或多個被取代的 NEP,或

  • 使 ndarray.__array_namespace__() 傳回一個隱藏的命名空間(甚至另一個新的公開命名空間)以及相容的函數,

  • 完全不實作陣列 API 標準支援。

與陣列 API 標準相比,被取代的 NEP 都存在一些缺點,並且到目前為止,已經對該標準投入了大量工作 - 以及其他關鍵函式庫的採用。因此,這些替代方案並不吸引人。鑑於對此主題的濃厚興趣,無所作為也不具吸引力。「隱藏命名空間」選項將是對本提案的較小變更。我們不希望這樣做,因為這會導致重複的實作仍然存在、更複雜的實作(例如,靜態型別的潛在問題),並且仍然存在兩種基本上相同的 API 風格。

從 NumPy 中移除 numpy.array_api 的替代方案是將其保留在目前的位置,因為它仍然有用 - 這是測試下游程式碼是否真正在陣列函式庫之間可移植的最佳方法。這是一個非常合理的替代方案,但是,稍微傾向於採用該模組並將其轉變為獨立套件。

討論#

參考文獻和註腳#