簡體   English   中英

Python 切片操作方法,我知道 Python 切片,但如何使用內置切片對象呢?

[英]Python slice how-to, I know the Python slice but how can I use built-in slice object for it?

內置函數slice什么用,我該如何使用?
我知道的 Pythonic 切片的直接方式 - l1[start:stop:step] 我想知道我是否有切片對象,那么我如何使用它?

如果使用 [start:end:step] 表示法,您可以通過調用具有相同字段的切片來創建切片:

sl = slice(0,4)

要使用切片,只需將它作為索引傳遞給列表或字符串:

>>> s = "ABCDEFGHIJKL"
>>> sl = slice(0,4)
>>> print(s[sl])
'ABCD'

假設您有一個固定長度文本字段的文件。 您可以定義一個切片列表,以便輕松地從此文件中的每個“記錄”中提取值。

data = """\
0010GEORGE JETSON    12345 SPACESHIP ST   HOUSTON       TX
0020WILE E COYOTE    312 ACME BLVD        TUCSON        AZ
0030FRED FLINTSTONE  246 GRANITE LANE     BEDROCK       CA
0040JONNY QUEST      31416 SCIENCE AVE    PALO ALTO     CA""".splitlines()


fieldslices = [slice(*fielddef) for fielddef in [
    (0,4), (4, 21), (21,42), (42,56), (56,58),
    ]]
fields = "id name address city state".split()

for rec in data:
    for field,sl in zip(fields, fieldslices):
        print("{} : {}".format(field, rec[sl]))
    print('')

打印:

id : 0010
name : GEORGE JETSON    
address : 12345 SPACESHIP ST   
city : HOUSTON       
state : TX

id : 0020
name : WILE E COYOTE    
address : 312 ACME BLVD        
city : TUCSON        
state : AZ

id : 0030
name : FRED FLINTSTONE  
address : 246 GRANITE LANE     
city : BEDROCK       
state : CA

id : 0040
name : JONNY QUEST      
address : 31416 SCIENCE AVE    
city : PALO ALTO     
state : CA

序列后面的方括號表示索引或切片,具體取決於括號內的內容:

>>> "Python rocks"[1]    # index
'y'
>>> "Python rocks"[1:10:2]    # slice
'yhnrc'

這兩種情況都由序列的__getitem__()方法處理(或__setitem__()如果在等號的左側。)索引或切片作為單個參數傳遞給方法,Python 這樣做的方式是通過將切片符號(在本例中為1:10:2 )轉換為切片對象: slice(1,10,2)

因此,如果您要定義自己的類似序列的類或覆蓋另一個類的__getitem____setitem____delitem__方法,則需要測試 index 參數以確定它是int還是slice ,並進行相應的處理:

def __getitem__(self, index):
    if isinstance(index, int):
        ...    # process index as an integer
    elif isinstance(index, slice):
        start, stop, step = index.indices(len(self))    # index is a slice
        ...    # process slice
    else:
        raise TypeError("index must be int or slice")

slice對象具有三個屬性: startstopstep ,以及一個方法: indices ,它接受一個參數,對象的長度,並返回一個三元組: (start, stop, step)

>>> class sl:
...  def __getitem__(self, *keys): print keys
...     
>>> s = sl()
>>> s[1:3:5]
(slice(1, 3, 5),)
>>> s[1:2:3, 1, 4:5]
((slice(1, 2, 3), 1, slice(4, 5, None)),)
>>>

slice函數返回切片對象 Slice 對象是 Python 的內部類型之一,針對讀取性能進行了優化——它們的所有屬性都是只讀的。

如果希望更改默認行為,更改slice可能很有用。 例如, lxml使用切片符號來訪問 DOM 元素(但是,我自己還沒有確認他們是如何做到的)。

在嘗試回答Subset a string based on variable 時,我回想起 numpy 有一種語法上很好的方式來定義切片對象:

>>> import numpy as np
>>> s = "The long-string instrument is a musical instrument in which the string is of such a length that the fundamental transverse wave is below what a person can hear as a tone."
>>> z = np.s_[18:26]  # in this case same as slice(18, 26, None)
>>> s[z]
'strument'

這里解決的問題是如何將切片存儲在變量中以備后用,而np.s_允許這樣做。 是的,它不是內置的,但是由於原始問題被重定向到這里,我覺得我的答案也屬於這里。 此外,numpy 是將如此先進的切片功能添加到 Python IIRC 的原因之一。

一個更復雜的“切片”的例子:

>>> data = np.array(range(6)).reshape((2, 3))
>>> z = np.s_[:1, 1:2]
>>> data[z]
array([[1]])
>>> data
array([[0, 1, 2],
       [3, 4, 5]])
>>> z
(slice(None, 1, None), slice(1, 2, None))

其中 z 現在是切片元組。

切片對象允許您以編程方式生成和操作切片。 特別是對於多維 numpy 數組,尤其是如果您事先不知道維度,您可能希望即時構建切片以指定所需的軸或維度。

import numpy as np
dimension = np.random.randint(10) # Might have up to 10 dimensions
shape = []
for d in range(dimension):
    shape.append(np.random.randint(10))
zz = np.random.rand(tuple(shape))
print(zz)
>>> array([[0.68379351, 0.50854469, 0.64578775, 0.73441699, 0.28977396],
           [0.88797164, 0.81603025, 0.63978659, 0.22677299, 0.93455738],
           [0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249],
           [0.88561035, 0.93378367, 0.12124208, 0.25600301, 0.96035638]])

在這里,我們的數據最終是二維的(4×5),但不能保證這一點。 你將如何從zz請求切片?

一個問題是我無法操作 Python 的切片符號。 它不是切片操作之外的有效語法。

my_slice = 2:3:1
>>> SyntaxError: Invalid Syntax

如果我可以在一個循環中構建我想要的確切切片請求,我可以構建一個字符串怎么辦? 那不會很棒嗎? 我的意思是,您當然可以使用字符串來執行此操作,但這會很麻煩並且需要eval

your_slice_definitions = [(2,3,1), *[(None, None, None)]*(zz.ndim - 1)] 
my_slice_str = ""
for slice_start, slice_end, slice_step in your_slice_definitions:
    my_slice_str += "{}:{}:{},".format(slice_start, slice_end, slice_step)
eval("zz["+my_slice_str+"])

所以我們在這里: slice對象讓你做到這一點。 您可以即時組裝它們的列表和元組,將它們作為函數參數傳遞,對它們進行排序,對它們進行混洗,等等。

my_slices = []
for slice_start, slice_end, slice_step in your_slice_definitions:
    my_slices += slice(slice_start, slice_end, slice_step)
print(zz[my_slices])
>>> array([[0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249]])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM