File: LP6E/Chapter30/contains.py
def trace(msg, end=''):
print(f'{msg} ', end=end) # print sans newline
class Iters:
def __init__(self, value):
self.data = value
def __getitem__(self, i): # Fallback for iteration
trace(f'@get[{i}]') # Also for index, slice
return self.data[i]
def __iter__(self): # Preferred for iteration
trace('@iter') # Allows only one active iterator
self.ix = 0
return self
def __next__(self):
trace('@next')
if self.ix == len(self.data): raise StopIteration
item = self.data[self.ix]
self.ix += 1
return item
def __contains__(self, x): # Preferred for 'in' membership
trace('@contains')
return x in self.data
def self_test(Iters):
X = Iters([1, 2, 3, 4]) # Make one instance
tests = 'In', 'For', 'Comp', 'Map', 'Manual'
for test in tests:
trace(test.ljust(max(map(len, tests)) + 1))
match test:
case 'In':
trace(3 in X) # Membership
case 'For':
for i in X: # for-loop iteration
trace(i, end='| ')
case 'Comp':
trace([i ** 2 for i in X]) # Other Iteration tools
case 'Map':
trace(list(map(bin, X)))
case 'Manual':
I = iter(X) # Manual iteration
while True:
try:
trace(next(I), end='| ')
except StopIteration:
break
print()
if __name__ == '__main__': self_test(Iters) # Test Iters here