Si un objeto no tiene una __contains__implementación, inrecurre a un valor predeterminado que básicamente funciona así:
def default__contains__(self, element):
for thing in self:
if thing == element:
return True
return False
Y si un objeto no tiene una __iter__implementación, forrecurre a un valor predeterminado que básicamente funciona así:
def default__iter__(self):
i = 0
try:
while True:
yield self[i]
i += 1
except IndexError:
pass
Estos valores predeterminados se utilizan incluso si el objeto no pretende ser una secuencia.
Su 1 in fy las 5 in fpruebas están utilizando los retrocesos predeterminados para iny for, lo que lleva al comportamiento observado. 1 in fencuentra de 1inmediato, pero __getitem__nunca regresa 5, por lo que 5 in fcorre para siempre.
(Bueno, en realidad, en la implementación de referencia de Python, la __iter__reserva predeterminada almacena el índice en una variable de nivel C de tipo Py_ssize_t, por lo que si espera lo suficiente, esa variable se maximiza y Python genera un OverflowError . Si vio eso, usted debe estar en una compilación de Python de 32 bits. Las computadoras no han existido lo suficiente como para que alguien pueda acceder a eso en una Python de 64 bits).
foryin, anterior a la introducción de__iter__y__contains__. Consulte la documentación de Python 1.4 aquí y aquí .