What explains the following behavior:
class Foo: def __getitem__(self, item): print("?") return 1 f = Foo() 1 in f # prints one ? and returns True 5 in f # prints ? forever until you raise a Keyboard Exception # Edit: eventually this fails with OverflowError: iter index too large
If an object doesn't have a __contains__ implementation, in falls back on a default that basically works like this:
def default__contains__(self, element): for thing in self: if thing == element: return True return False And if an object doesn't have an __iter__ implementation, for falls back on a default that basically works like this:
def default__iter__(self): i = 0 try: while True: yield self[i] i += 1 except IndexError: pass These defaults are used even if the object is not intended to be a sequence.
Your 1 in f and 5 in f tests are using the default fallbacks for in and for, leading to the observed behavior. 1 in f finds 1 immediately, but your __getitem__ never returns 5, so 5 in f runs forever.
(Well, actually, on the reference implementation of Python, the default __iter__ fallback stores the index in a C-level variable of type Py_ssize_t, so if you wait long enough, that variable maxes out and Python raises an OverflowError. If you saw that, you must be on a 32-bit Python build. Computers haven't existed long enough for anyone to hit that on a 64-bit Python.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With