Usuwanie elementu z wyciągnięcie iteracja to zazwyczaj powodują RuntimeError: dictionary changed size during iteration
wyjątkiem:Dlaczego modyfikowanie dict podczas iteracji nie zawsze powoduje wyjątek?
d = {1: 2}
# exception raised
for k in d:
del d[k]
Aby być bardziej precyzyjnym, sama delecja uda. Jednakże, aby przejść do kolejnej rundy iteracji, interpreter musi wywołać next(it)
, gdzie it
jest iteratorem przez słownik, który wcześniej uzyskał. W tym momencie next()
zauważy, że rozmiar słownika się zmienił i narzeka.
Jak dotąd tak dobrze. Ale co, jeśli oboje usunąć i dodać element do słownika:
d = {1: 1}
# no exception raised
for k in d:
# order of next two lines doesn't matter
d[k*10] = k*10
del d[k]
Jestem prawie pewien, że to nie jest bezpieczne (docs sugerować ani wkładki ani usuwać wolno podczas iteracji). Dlaczego tłumacz umożliwia działanie tego kodu bez błędu?
Podejrzewam tylko, że zbyt drogie jest sprawdzenie, które iteratory są unieważniane za każdym razem, gdy wywoływana jest metoda wstawiania lub usuwania. Tak więc dict
nie stara się być idealnym o podniesienie tego wyjątku. Zamiast tego, po prostu śledzi rozmiar słownika wewnątrz każdego iteratora i sprawdza, czy nie zmieniło się, gdy iterator jest proszony o przejście do następnego elementu. Czy nie ma podejścia, które umożliwiłoby pełną walidację przy niskim koszcie?
Szukasz czegoś, co sprawi, że twoja pętla stanie się bardziej niezawodna, czy chcesz omówić szczegóły implementacji Pythona? –
Wygląda na to, że chcesz mieć niezmienne klucze słownikowe w pętli. Nie sądzę, żeby było to wykonalne. – DyZ
@KlausD. Hmm, myślę, że jedno i drugie? Jeśli istnieje technika, która może to zrobić, rozważyłbym skorzystanie z niego osobiście. Ale aby zrozumieć jego koszty (czas pracy, złożoność kodu, itp.), Byłoby dla mnie ważne, aby wiedzieć, dlaczego CPython go nie używa. – max