2011-08-17 69 views
5

我讀了一些關於python3中的slice的內容。 然後我寫了一個程序,試圖實現getitem(self,slice(s))。 代碼低於:[python]:如何在python3中實現切片?

class NewList: 
    def __init__(self, lst): 
     print('new list') 
     self._list = lst 
    def __getitem__(self, x): 
     if type(x) is slice: 
      return [ self._list[n] for n in range(x.start, x.stop, x.step) ] #error? 
     else: 
      return self._list[x] 
    ... 

nl1 = NewList([1,2,3,4,5]) 
nl1[1:3] #error occurs 

後來我發現x.step是無,這令範圍引發異常。 那麼,我該如何實現getitem方法?

+0

此外,你的'NewList'類應該繼承'list' ... – JBernardo

+0

@JBernardo - 你是否應該避免明確地使用切片對象? – Alcott

回答

2

您需要使用slice.indices方法。鑑於您的序列的長度,它返回開始的元組,停止步驟:

>>> s = slice(2, 5, None) 
>>> s.indices(10) 
(2, 5, 1) 

>>> [x for x in range(*s.indices(10))] 
[2, 3, 4] 

>>> s.indices(3) 
(2, 3, 1) 

>>> s.indices(0) 
(0, 0, 1) 
0

x.step or 1怎麼樣?

class NewList: 
    def __init__(self, lst): 
     print('new list') 
     self._list = lst 
    def __getitem__(self, x): 
     if type(x) is slice: 
      return [ self._list[n] for n in range(x.start, x.stop, x.step or 1) ] #error? 
     else: 
      return self._list[x] 

nl1 = NewList([1,2,3,4,5]) 
nl1[1:3] 
+0

雅,這是繞過這個問題的方法,但根據我所讀到的,沒有。 – Alcott

2

如果x是一個切片,你可以做一樣的其他條件:

return self._list[x] 
+0

絕對是的,但我只想知道如何自己做 – Alcott

+0

@Alcott,不知道你是什麼意思的「自己動手」。 –

+1

對不起,我的意思是我想知道__getitem __(self,slice)是如何在列表中實現的。 – Alcott

4

在你不知道你的對象的長度有明顯的伎倆來規避這種強制性參數的情況。例如一個無限序列的的GetItem可以是這樣的:

def __getitem__(self, key) : 
    if isinstance(key, slice) : 
     m = max(key.start, key.stop) 
     return [self[ii] for ii in xrange(*key.indices(m+1))] 
    elif isinstance(key, int) : 
     #Handle int indices 

,如果你不給啓動和停止但檢查無本可以處理得它只會失敗。

+0

'xrange'不存在於python3中,我們應該使用'range'。也使用這個實現你不能像'[:4]'那樣切片,因爲'max'不能處理'None'類型。相反,你應該檢查start和stop是否不是'None',如果是,則分別將它們分配給零和len項。此外,在'range'中也包含'key.step'是很好的選擇。 – sazary