Could someone explain what is going on under the hood and why this program does not finish?
class A:
def __getitem__(self, key):
return 1
print(*A())
Could someone explain what is going on under the hood and why this program does not finish?
class A:
def __getitem__(self, key):
return 1
print(*A())
This program doesn't finish because the class you defined is iterable, using the old sequence iteration protocol. Basically, __getitem__ is called with integers increasing from 0, ..., n until an IndexError is raised.
>>> class A:
... def __getitem__(self, key):
... return 1
...
>>> it = iter(A())
>>> next(it)
1
>>> next(it)
1
>>> next(it)
1
>>> next(it)
1
You are unpacking an infinite iterator, so eventually you'll run out of memory.
From the iter docs:
Without a second argument, object must be a collection object which supports the iteration protocol (the
__iter__()method), or it must support the sequence protocol (the__getitem__()method with integer arguments starting at 0). If it does not support either of those protocols, TypeError is raised.
According to the documentation of object.__getitem__ it is supposed to raise IndexError or KeyError when a non-existent elements is requested.
You ignore the key and return a constant—so you never indicate that it is finished.
class A:
n = 0
def __getitem__(self, _): # ignoring the key
A.n += 1
if A.n > 1000:
raise IndexError()
return A.n
print(*A())
will finish and print up to 1000 - yours never does - when decompositioning your class you are never done.
Output:
1 2 3 4 5 ... 998 999 1000