Il metodo getitem è stato aggiunto a Python come parte del protocollo delle sequenze e dei mapping. Grazie a questo metodo magico, le collezioni standard (list, tuple, dict, ecc.) supportano l'accesso per indice, chiave e slice. Nelle classi utente, questo metodo consente agli oggetti di comportarsi come "collezioni".
Senza l'implementazione di getitem, una classe utente non supporta l'indicizzazione e l'iterazione tramite for. L'implementazione solo per indici semplici non è applicabile se vogliamo un funzionamento completo con gli slice, e ignorare le varietà di indice porterà a errori.
Implementare getitem per supportare sia indici che oggetti di tipo slice, separandoli nel trattamento. Ciò consente di utilizzare oggetti personalizzati nelle strutture standard di Python (ad esempio, per supportare gli slice your_obj[1:5]).
Esempio di codice:
class MyRange: def __init__(self, n): self.n = n def __getitem__(self, item): if isinstance(item, int): # Indice individuale if 0 <= item < self.n: return item * 2 raise IndexError('indice fuori intervallo') elif isinstance(item, slice): # Slice return [self[i] for i in range(*item.indices(self.n))] else: raise TypeError('Tipo di argomento non valido: {}'.format(type(item))) mr = MyRange(10) print(mr[3]) # 6 print(mr[2:5]) # [4, 6, 8]
Caratteristiche chiave:
L'implementazione solo di getitem consente di assegnare valori per indice?
No. Per supportare l'assegnazione (your_obj[i] = valore) è necessario implementare setitem. getitem è responsabile solo per la lettura.
getitem deve necessariamente restituire una lista per uno slice, come fa list?
No. L'importante è restituire una "sequenza" in base al significato della classe (puoi restituire lo stesso tipo o, ad esempio, un tuple). L'importante è che sia significativo nel contesto del compito.
Perché a volte si verifica l'errore TypeError: 'MyClass' object is not subscriptable?
Questo messaggio appare se provi a eseguire my_obj[0], mentre la classe non implementa getitem. Affinché la classe sia subscriptable (supporti []), questo metodo è obbligatorio.
È stato implementato getitem solo per int, dimenticando slice. Qualsiasi tentativo di my_obj[2:5] porta a TypeError e interruzione dell'intero algoritmo di elaborazione delle collezioni.
Pro:
Contro:
getitem è implementato con un trattamento separato per slice e int. Slice e indici funzionano, i metodi list(), map(), iterazione sono supportati senza sforzi aggiuntivi.
Pro:
Contro: