2011-08-17 10 views
5

Leí algo sobre slice en python3. Luego escribí un programa, traté de implementar getitem (self, slice (s)). código va a continuación:[python]: ¿cómo implementar slice en 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 

Luego descubrí x.step es Ninguno, lo que hizo rango de lanzar una excepción. Entonces, ¿cómo debo implementar el método getitem?

+0

Además, su clase 'NewList' debe heredar de' list' ... – JBernardo

+0

@JBernardo - ¿Quiere decir que debería evitar el uso de objetos de división explícitamente? – Alcott

Respuesta

2

Es necesario utilizar el método slice.indices. Teniendo en cuenta la longitud de su secuencia, devuelve una tupla de arranque, parada, paso:

>>> 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

¿qué tal 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

ya, es una manera de eludir el problema, pero de acuerdo con lo que leo, no. – Alcott

2

Si x es una rebanada, puede hacer lo mismo que la otra condición:

return self._list[x] 
+0

absolutamente sí, pero solo quiero saber cómo hacerlo yo mismo – Alcott

+0

@Alcott, no estoy seguro de lo que quiere decir con "hágalo por mí mismo". –

+1

lo siento, quiero decir que quiero saber cómo el __getitem __ (self, slice) implementado en la lista. – Alcott

4

En el caso de que usted no sabe la duración de su objeto no es un truco obvio para eludir este parámetro obligatorio. Por ejemplo GetItem de una secuencia infinita puede tener este aspecto:

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 

Sólo se producirá un error si no damos iniciar y detener pero con la comprobación de esta Ninguno podía ser manejado también.

+0

'xrange' no existe en python3, en su lugar deberíamos usar' range'. Además, al usar esta implementación no puede tener segmentos como '[: 4]' porque 'max' no puede manejar el tipo' Ninguno'. En su lugar, debe verificar si start y stop no son 'None', y si lo son, asígnelos a cero y len de ítems, respectivamente. Además, es bueno incluir 'key.step' en' range' también. – sazary