Si un objet n'a pas d' __contains__
implémentation, in
retombe sur une valeur par défaut qui fonctionne essentiellement comme ceci:
def default__contains__(self, element):
for thing in self:
if thing == element:
return True
return False
Et si un objet n'a pas d' __iter__
implémentation, for
retombe sur une valeur par défaut qui fonctionne essentiellement comme ceci:
def default__iter__(self):
i = 0
try:
while True:
yield self[i]
i += 1
except IndexError:
pass
Ces valeurs par défaut sont utilisées même si l'objet n'est pas destiné à être une séquence.
Vos tests 1 in f
et 5 in f
utilisent les substitutions par défaut pour in
et for
, conduisant au comportement observé. 1 in f
trouve 1
immédiatement, mais votre __getitem__
ne revient jamais 5
, donc 5 in f
fonctionne pour toujours.
(Eh bien, en fait, sur l'implémentation de référence de Python, le __iter__
repli par défaut stocke l'index dans une variable de type C de type Py_ssize_t
, donc si vous attendez assez longtemps, cette variable atteint son maximum et Python déclenche une OverflowError . Si vous avez vu cela, vous doit être sur une version Python 32 bits. Les ordinateurs n'existent pas depuis assez longtemps pour que quiconque puisse l'atteindre sur un Python 64 bits.)
for
etin
, antérieures à l'introduction de__iter__
et__contains__
. Voir la documentation Python 1.4 ici et ici .