Se um objeto não tiver uma __contains__
implementação,in
retornará a um padrão que basicamente funciona assim:
def default__contains__(self, element):
for thing in self:
if thing == element:
return True
return False
E se um objeto não tiver uma __iter__
implementação,for
retornará a um padrão que basicamente funciona assim:
def default__iter__(self):
i = 0
try:
while True:
yield self[i]
i += 1
except IndexError:
pass
Esses padrões são usados mesmo que o objeto não seja uma sequência.
Seus testes 1 in f
e 5 in f
estão usando os fallbacks padrão para in
e for
, levando ao comportamento observado. 1 in f
encontra 1
imediatamente, mas seu __getitem__
nunca retorna 5
, então5 in f
corre para sempre.
(Bem, na implementação de referência do Python, o __iter__
fallback padrão armazena o índice em uma variável do tipo C-level Py_ssize_t
, portanto, se você esperar o suficiente, essa variável atinge o limite máximo e o Python gera um OverflowError . Se você viu isso, deve estar em uma versão Python de 32 bits. Os computadores não existem o suficiente para que alguém possa acessá-la em um Python de 64 bits.)
for
ein
, anteriores à introdução de__iter__
e__contains__
. Veja a documentação do Python 1.4 aqui e aqui .