Historia de la pregunta:
Las secuencias son uno de los conceptos más antiguos y básicos en Python. Ejemplos clásicos son listas (list), cadenas (str), y tuplas (tuple). Se ha definido un protocolo especial para interactuar con secuencias: es necesario implementar los métodos __getitem__ y __len__. Esto permite que un objeto se comporte "como una secuencia" — soportar indexación, cortes, trabajo en bucles y hasta algunas funciones estándar.
Problema:
Sin la implementación correcta de estos métodos, una clase de usuario no podrá trabajar con operaciones de indexación, bucles for, funciones como len(). A menudo, los desarrolladores principiantes implementan solo uno de los métodos, no consideran el manejo de excepciones, no implementan el soporte para cortes (slice) y obtienen un comportamiento incorrecto o inesperado.
Solución:
Es necesario implementar el método __getitem__(self, key) para soportar la indexación y los cortes, así como __len__(self) para trabajar con la función len() y una correcta iterabilidad. Para soportar cortes, es necesario diferenciar el tipo de key en __getitem__ y manejar correctamente los objetos slice.
Ejemplo de código:
def is_even(n): return n % 2 == 0 class EvenSequence: def __init__(self, size): self.size = size def __getitem__(self, index): if isinstance(index, slice): return [x for x in range(self.size)[index] if is_even(x)] if index < 0 or index >= self.size: raise IndexError('Índice fuera de límites') return index if is_even(index) else None def __len__(self): return self.size
Características clave:
¿Se puede limitar solo a implementar el método getitem para que el objeto funcione como una secuencia?
Parcialmente. Si se implementa solo __getitem__, se podrá iterar sobre el objeto mediante for e indexar elementos, pero len() no funcionará.
Ejemplo de código:
class SeqOnlyGetitem: def __getitem__(self, index): if index >= 10: raise IndexError return index * 2 s = SeqOnlyGetitem() for x in s: print(x) # Funciona (iterable) # print(len(s)) # Error TypeError
¿Cómo manejar índices negativos y qué pasará si no se consideran?
Los índices negativos son una característica clave de las secuencias en Python. Si no se manejan, el objeto se comporta de manera inesperada para el usuario.
class NegIndex: def __init__(self, data): self.data = data def __getitem__(self, index): if index < 0: index += len(self.data) return self.data[index]
¿Es necesario implementar contains o iter para su clase de Sequence?
No es obligatorio. Si se implementan __getitem__ y __len__, la función in funcionará, y for las utilizará para iterar. La implementación de estos métodos directamente generalmente no es necesaria, pero puede mejorar el rendimiento.
Un desarrollador implementó solo getitem para su clase solo para índices positivos. El módulo pasó parte de las pruebas unitarias, pero en el uso real, al intentar acceder a un índice inexistente o un índice negativo, todo falló.
Ventajas:
Desventajas:
El equipo implementó ambos métodos (getitem y len), consideraron los cortes, índices negativos, y lanzaron excepciones correctas. La clase resultante funcionó en todos los casos estándar de Python.
Ventajas:
Desventajas: