本節書摘來自華章社群《編寫高品質python代碼的59個有效方法》一書中的第5條:了解切割序列的辦法,作者[美]布雷特·斯拉特金(brett slatkin),更多章節内容可以通路雲栖社群“華章社群”公衆号檢視
第5條:了解切割序列的辦法
python提供了一種把序列切成小塊的寫法。這種切片(slice)操作,使得開發者能夠輕易地通路由序列中的某些元素所構成的子集。最簡單的用法,就是對内置的list、str和bytes進行切割。切割操作還可以延伸到實作了__getitem__和__setitem__這兩個特殊方法的python類上(參見本書第28條)。
切割操作的基本寫法是somelist[start:end],其中start(起始索引)所指的元素涵蓋在切割後的範圍内,而end(結束索引)所指的元素則不包括在切割結果之中。
如果從清單開頭擷取切片,那就不要在start那裡寫上0,而是應該把它留白,這樣代碼看起來會清爽一些。
如果切片一直要取到清單末尾,那就應該把end留白,因為即便寫了,也是多餘。
在指定切片起止索引時,若要從清單尾部向前算,則可使用負值來表示相關偏移量。如果采用下面這些寫法來切割清單,那麼即便是剛剛接觸代碼的人也能立刻明白程式的意圖。由于這些寫法都不會令人驚訝,是以筆者推薦大家在代碼中放心地使用。
切割清單時,即便start或end索引越界也不會出問題。利用這一特性,我們可以限定輸入序列的最大長度。
反之,通路清單中的單個元素時,下标不能越界,否則會導緻異常。
請注意,如果使用負變量作為start索引來切割清單,那麼在極個别情況下,可能會導緻奇怪的結果。例如,somelist[-n:]這個表達式,在n大于1時可以正常運作,如當n為3時,somelist[-3:]的結果是正常的。然而,當n為0時,表達式somelist[-0:]則成了原清單的一份拷貝。
對原清單進行切割之後,會産生另外一份全新的清單。系統依然維護着指向原清單中各個對象的引用。在切割後得到的新清單上進行修改,不會影響原清單。
在指派時對左側清單使用切割操作,會把該清單中處在指定範圍内的對象替換為新值。與元組(tuple)的指派(如a, b = c[:2])不同,此切片的長度無需新值的個數相等。位于切片範圍之前及之後的那些值都保留不變。清單會根據新值的個數相應地擴張或收縮。
如果對指派操作右側的清單使用切片,而把切片的起止索引都留白,那就會産生一份原清單的拷貝。
如果對指派操作左側的清單使用切片,而又沒有指定起止索引,那麼系統會把右側的新值複制一份,并用這份拷貝來替換左側清單的全部内容,而不會重新配置設定新的清單。
要點
不要寫多餘的代碼:當start索引為0,或end索引為序列長度時,應該将其省略。
切片操作不會計較start與end索引是否越界,這使得我們很容易就能從序列的前端或後端開始,對其進行範圍固定的切片操作(如a[:20]或a[-20:])。
對list指派的時候,如果使用切片操作,就會把原清單中處在相關範圍内的值替換成新值,即便它們的長度不同也依然可以替換。