En Python, el protocolo 'Sequence' define una interfaz para objetos que se pueden indexar e iterar, como listas o tuplas. Históricamente, las secuencias aparecieron prácticamente desde las primeras versiones de Python para respaldar las operaciones naturales con estructuras de datos: indexación, cortes, iteración sobre elementos.
Problema — para que una clase de usuario se comporte como una secuencia, no son suficientes solo los métodos iter y next. Para un soporte completo del comportamiento de la secuencia, se requieren métodos adicionales.
Solución — para implementar su propio tipo de secuencia, debe definir los métodos getitem (necesario para indexación y cortes) y opcionalmente len (para len() y verificación de longitud). Así, el objeto admitirá la iteración, acceso por índice, trabajo con cortes, así como muchas operaciones estándar de Python con secuencias.
Ejemplo de código:
class MyCounter: def __init__(self, stop): self._stop = stop def __getitem__(self, index): if 0 <= index < self._stop: return index * 10 else: raise IndexError('Fuera de rango') def __len__(self): return self._stop c = MyCounter(5) print(c[3]) # 30 print(len(c)) # 5 for x in c: print(x)
Características clave:
Si solo implemento iter y next, ¿se convertirá mi objeto en una secuencia (Sequence)?
No. Tal objeto será solo iterable (iterable), pero no una secuencia. No soportará indexación, cortes, ni las funciones estándar de objetos similares a listas.
¿Es necesario implementar getitem para soportar el ciclo for?
No es necesario. Si iter está implementado, for funcionará. Pero si no hay iter, el intérprete intentará usar getitem, comenzando desde el índice 0, hasta que se produzca un IndexError. Por lo tanto, para la secuencia, es suficiente con getitem.
¿Se puede implementar getitem solo para int y no para slice?
Técnicamente el objeto funcionará para c[0], pero intentar tomar un corte c[1:4] fallará. Para soportar cortes, getitem debe poder manejar objetos de tipo slice (mire slice.indices e isinstance(key, slice)).
Ejemplo de código:
class S: def __getitem__(self, idx): if isinstance(idx, slice): return [x for x in range(idx.start or 0, idx.stop or 10, idx.step or 1)] return idx * 2
Implementaron una estructura personalizada, definiendo solo iter, pensando que ahora se pueden utilizar cortes e indexación.
Ventajas:
Desventajas:
La clase implementa getitem con soporte para trabajar con cortes y índices int, así como len.
Ventajas:
Desventajas: