Jeśli obiekt nie ma __contains__
implementacji, in
wraca do wartości domyślnej, która w zasadzie działa w następujący sposób:
def default__contains__(self, element):
for thing in self:
if thing == element:
return True
return False
A jeśli obiekt nie ma __iter__
implementacji, for
wraca do wartości domyślnej, która w zasadzie działa w następujący sposób:
def default__iter__(self):
i = 0
try:
while True:
yield self[i]
i += 1
except IndexError:
pass
Te wartości domyślne są używane, nawet jeśli obiekt nie jest sekwencją.
Twoje 1 in f
i 5 in f
testy wykorzystują domyślne awarie dla in
i for
, co prowadzi do zaobserwowanego zachowania. 1 in f
znajduje 1
natychmiast, ale __getitem__
nigdy nie wraca 5
, więc 5 in f
działa wiecznie.
(Cóż, w rzeczywistości w referencyjnej implementacji Pythona domyślny system __iter__
rezerwowy przechowuje indeks w zmiennej typu C Py_ssize_t
, więc jeśli zaczekasz wystarczająco długo, ta zmienna osiągnie maksimum i Python zgłosi błąd OverflowError . Jeśli to zobaczyłeś, możesz musi być w 32-bitowej wersji Pythona. Komputery nie istniały wystarczająco długo, aby ktokolwiek mógł je uruchomić w 64-bitowym Pythonie).
for
iin
poprzedzające wprowadzenie__iter__
i__contains__
. Zobacz dokumentację Python 1.4 tutaj i tutaj .