我觀察到 ifa是一個包含元素的串列(或一個 numpy 陣列)[1,2,3]并且我要求a[1:-1:-1],然后我得到空串列。我希望[2,1]假設切片跨越從 1 到 -1 遞減的可獲取索引,不包括最后一個值(即不包括 -1),即索引 1 和 0。
實際行為可能有一些理由,但是當需要a從某個通用索引開始以相反的順序i索引(排除)的陣列的子陣列時,會使事情比預期的更復雜。i m有人會傾向于寫a[i m-1:i-1:-1],但如果設定為 0,這會突然中斷。它對除零i以外的所有人都有效,這一事實i看起來像是一種令人討厭的不一致。顯然,有一些解決方法:
- 可以通過陣列長度來撰寫
a[i m-1-n:i-1-n:-1]偏移所有內容;或者-nn - 一個可以寫
a[i:i m][::-1]。
但是,在情況 1 中,知道陣列長度的需要顯得相當不自然,而在情況 2 中,如果切片是在緊密回圈中完成的,則雙索引似乎不是非常合理的開銷。
是否有任何重要的原因讓我想念我的行為是很重要的?
NumPy 社區是否考慮過這個問題?
有比我想出的更好的解決方法嗎?
uj5u.com熱心網友回復:
Numpy 已經從 Python 的序列索引中采用了這種行為,這里解釋了規則(有關一些歷史,請參見下文)。具體腳注 (5) 內容如下:
sfromitojwith step的切片k被定義為具有索引的專案序列,x = i n*k使得0 <= n < (j-i)/k. 換句話說,索引是i、i k、等i 2*k,在達到i 3*k時停止j(但從不包括j)。何時k為正,如果它們更大i,j則歸結為。len(s)Whenk是負數,如果它們更大i,j則歸結為。len(s) - 1如果iorj被省略 orNone,它們將成為“結束”值(結束取決于 的符號k)。注意,k不能為零。如果k為 None,則將其視為1。
所以指數是從乘數生成n的0 <= n < (j-i)/k。對于您的具體示例(j-i)/k < 0,因此不計算索引。
對于 Numpy 陣列a[i:i m][::-1]生成底層陣列的視圖,即它的開銷可以忽略不計,因此似乎是一個有效的解決方案。它清楚地傳達了意圖,即“從某個通用索引開始以相反的順序獲取陣列的子陣列aii m” 。
或者,如果為零,您可以None用作停止引數:i
a[i m-1:(None if i==0 else i-1):-1]
歷史
最初,Python 通過__getslice__(另請參見此處)實作了切片語法,它不允許使用 step 引數,即它只使用 2-argument 形式:a[i:j]。這是通過內置序列實作的,例如list. 那時,大約在 1995 年左右,Numpy 的前身 Numerical Python 在MATRIX-SIG(特殊興趣小組)內開發和討論。這個前身實作了一個特定的型別,它也可以用來以與今天非常相似的形式Slice指定一個所謂的stride(現在) :例如。它被要求擴展 Python 的語法以允許今天已知的 3-form 切片:(參見例如這個執行緒)。這以stepslicea[Slice(None, None, 2)]a[::2]slice型別 和 將被傳遞給__getitem__而不是__getslice__. 所以當時,a[i:j]被解決為a.__getslice__(i, j)whilea[i:j:k]被解決為a.__getitem__(slice(i, j, k)). 那時,Numerical Python 甚至允許使用 2-form 進行“反向”切片,將第二個引數解釋為步幅(參見檔案;例如a[i:-1]相當于a[i::-1]陣列物件a)。陣列的索引是針對 Python 序列的索引如何作業的:包括開始索引,不包括停止索引(參見此處)。這也適用于負步幅(步),因此提供了今天可以觀察到的行為。這個決定可能是基于最小意外原則(對于“標準”Python用戶)。花了很長時間,直到 Python 2.3 為內置型別實作了包括 step 在內的擴展切片功能(請參閱what's new和docs;請注意,2.3 版本的檔案包含對帶有 step 的切片的錯誤描述,即為 2.4 版本修復)。
uj5u.com熱心網友回復:
-1 作為索引具有特殊含義 [1],它被替換為最高可能 = 串列的最后一個索引。于是a[1:-1:-1]就變成a[1:2:-1]了空。
[1] 實際上,Python 中的所有負索引都是這樣作業的。-1 表示串列的最后一個元素,-2 表示倒數第二個元素,-3 表示其之前的元素,依此類推。
uj5u.com熱心網友回復:
List[1:-1:-1]表示List[開始索引:結束索引:跳轉]
串列中的索引:
| 數字 | 1 | 2 | 3 |
|---|---|---|---|
| 指數 | 0 | 1 | 2 |
| 指數 | -3 | -2 | -1 |
因此,如果我們獲取串列a[1,2,3]并找到a[1:-1:-1] 的串列意味著starting index = 1, ending index = -1, jump = -1
所以,串列遍歷
索引 1(即 number=2)到索引 -1(即 number=3)但跳轉 = -1(表示向后位置)
所以,回傳一個空串列
i.e. []
uj5u.com熱心網友回復:
正如其他人指出-1的終點具有特殊含義
In [66]: a=[1,2,3]
切片回到開頭最好用None:
In [68]: a[1::-1]
Out[68]: [2, 1]
In [69]: a[1:None:-1]
Out[69]: [2, 1]
使用可能跨越邊界的切片,任何一方都可能很棘手:
In [75]: [a[i 2-1:i-1:-1] for i in range(4)]
Out[75]: [[], [3, 2], [3], []]
簡化一點:
In [77]: [a[i 2:i:-1] for i in range(-1,3)]
Out[77]: [[], [3, 2], [3], []]
我們可以通過使用if子句來更正下邊界:
In [78]: [a[i 2:None if i<0 else i:-1] for i in range(-1,3)]
Out[78]: [[2, 1], [3, 2], [3], []]
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/463182.html
