Metoda getitem została dodana do Pythona jako część protokołu sekwencji i map. Za pomocą tej magicznej metody standardowe kolekcje (list, tuple, dict itd.) wspierają dostęp przez indeks, klucz i wycinek. W klasach użytkowników ta metoda pozwala obiektom zachowywać się "jak kolekcje".
Bez implementacji getitem klasa użytkownika nie wspiera indeksowania i iteracji przez for. Implementacja tylko dla prostych indeksów jest nieodpowiednia, jeśli chcemy pełnej obsługi wycinków (slice), a ignorowanie rodzajów indeksów prowadzi do błędów.
Zaimplementować getitem do wsparcia zarówno indeksów, jak i obiektów typu slice, rozdzielając je w obróbce. Pozwala to na użycie obiektów użytkownika w standardowych konstrukcjach Pythona (np. do wsparcia wycinków your_obj[1:5]).
Przykład kodu:
class MyRange: def __init__(self, n): self.n = n def __getitem__(self, item): if isinstance(item, int): # Indywidualny indeks if 0 <= item < self.n: return item * 2 raise IndexError('index out of range') elif isinstance(item, slice): # Wycinek return [self[i] for i in range(*item.indices(self.n))] else: raise TypeError('Invalid argument type: {}'.format(type(item))) mr = MyRange(10) print(mr[3]) # 6 print(mr[2:5]) # [4, 6, 8]
Kluczowe cechy:
Czy implementacja tylko getitem pozwala na przypisywanie wartości przez indeks?
Nie. Aby wspierać przypisywanie (your_obj[i] = value), trzeba zaimplementować setitem. getitem odpowiada tylko za odczyt.
Czy getitem musi zwracać listę na wycinku, jak list?
Nie. Najważniejsze — zwracać "sekwencję" z uwzględnieniem sensu klasy (można zwracać ten sam typ lub, na przykład, tuple). Ważne, aby miało to sens w kontekście zadania.
Dlaczego czasami pojawia się błąd TypeError: 'MyClass' object is not subscriptable?
Taki komunikat pojawia się, jeśli próbujesz wykonać my_obj[0], a klasa nie implementuje getitem. Aby klasa była subscriptable (wspierała []), ta metoda jest obowiązkowa.
Zaimplementowano getitem tylko dla int, zapomniano o slice. Każda próba my_obj[2:5] prowadzi do TypeError i awarii całego algorytmu przetwarzania kolekcji.
Zalety:
Wady:
getitem zaimplementowany z oddzielną obsługą slice i int. Wycinki i indeksy działają, metody list(), map(), iteracje są wspierane bez dodatkowego wysiłku.
Zalety:
Wady: