Napisałem niestandardowy obiekt kontenera.
Zgodnie z tą stroną muszę zaimplementować tę metodę na moim obiekcie:
__iter__(self)
Jednak po przejrzeniu linku do typów Iteratorów w podręczniku Python nie ma przykładów implementacji własnego.
Czy ktoś może opublikować fragment (lub link do zasobu), który pokazuje, jak to zrobić?
Kontener, który piszę, jest mapą (tj. Przechowuje wartości według unikalnych kluczy). dykty można iterować w następujący sposób:
for k, v in mydict.items()
W takim przypadku muszę mieć możliwość zwrócenia dwóch elementów (krotki?) W iteratorze. Nadal nie jest jasne, jak zaimplementować taki iterator (pomimo kilku uprzejmych odpowiedzi). Czy mógłby ktoś rzucić więcej światła na to, jak zaimplementować iterator dla obiektu kontenera podobnego do mapy? (tj. klasa niestandardowa, która działa jak dykt)?
some_list
zostały przekazane.some_list
zostanie wyczerpany.StopIteration
jest automatycznie wywoływana przez Pythona, gdy funkcja generatora zwraca, albo przez twoje jawne wywołanie,return
albo przez osiągnięcie końca funkcji (która jak wszystkie funkcje mareturn None
na końcu niejawny ). Jawne podnoszenieStopIteration
nie jest konieczne i od Pythona 3.5 faktycznie nie będzie działać (zobacz PEP 479 ): tak jak generatory zamieniają sięreturn
wStopIteration
jawneraise StopIteration
plikiRuntimeError
.Inną opcją jest dziedziczenie z odpowiedniej abstrakcyjnej klasy bazowej z modułu `collections, jak opisano tutaj .
Jeśli kontener jest własnym iteratorem, możesz dziedziczyć z
collections.Iterator
. Wystarczy wtedy zaimplementowaćnext
metodę.Oto przykład:
Podczas patrzenia na
collections
module, należy rozważyć dziedziczenie zSequence
,Mapping
lub inny abstrakcyjne klasy bazowej, jeżeli jest to bardziej właściwe. Oto przykład dlaSequence
podklasy:NB : Dziękuję Glennowi Maynardowi za zwrócenie mojej uwagi na potrzebę wyjaśnienia różnicy między iteratorami z jednej strony a kontenerami, które są iterowalne, a nie iteratorami z drugiej.
źródło
zwykle
__iter__()
po prostu zwraca self, jeśli już zdefiniowałeś metodę next () (obiekt generatora):oto przykład Dummy generatora:
ale
__iter__()
może być również używany w ten sposób: http://mail.python.org/pipermail/tutor/2006-J January / 044455.htmlźródło
Jeśli twój obiekt zawiera zestaw danych, z którymi chcesz powiązać iter obiektu, możesz oszukać i zrobić to:
źródło
hasattr
, użyjtry/except AttributeError
„Iterowalny interfejs” w Pythonie składa się z dwóch metod
__next__()
i__iter__()
.__next__
Funkcja jest najważniejsza, jak to określa zachowanie iterator - czyli funkcja określa, jakie wartości powinny być zwrócone następnego.__iter__()
Metoda służy do zresetowania punktu początkowego iteracji. Często okaże się, że__iter__()
może po prostu wrócić do siebie, gdy__init__()
jest używany do ustawienia punktu początkowego.Zobacz poniższy kod, aby zdefiniować odwróconą klasę, która implementuje „iterowalny interfejs” i definiuje iterator dla dowolnej instancji z dowolnej klasy sekwencji.
__next__()
Sposób zaczyna się na końcu sekwencji i zwraca wartość w odwrotnej kolejności sekwencji. Zwróć uwagę, że instancje z klasy implementującej „interfejs sekwencji” muszą definiować a__len__()
i__getitem__()
metodę.źródło
Aby odpowiedzieć na pytanie dotyczące mapowań : Twoje dane
__iter__
powinny iterować po kluczach mapowania. Poniżej znajduje się prosty przykład, który tworzy mapowaniex -> x * x
i działa na Pythonie3, rozszerzając mapowanie ABC.źródło
Jeśli nie chcesz dziedziczyć
dict
tak, jak sugerowali inni, oto bezpośrednia odpowiedź na pytanie, jak zaimplementować,__iter__
aby uzyskać surowy przykład niestandardowego dyktowania:To wykorzystuje generator, który jest dobrze opisany tutaj .
Ponieważ dziedziczymy po
Mapping
, musisz również zaimplementować__getitem__
i__len__
:źródło
Jedną z opcji, która może działać w niektórych przypadkach, jest ustawienie dziedziczenia z klasy niestandardowej
dict
. Wydaje się to logicznym wyborem, jeśli zachowuje się jak dykt; może to powinien być dykt. W ten sposób otrzymujesz darmową iterację w stylu dyktowania.Wynik:
źródło
na przykład dla inhert from dict, zmodyfikuj jego
iter
klawisz, na przykład, skip key2
w pętli forźródło