str = "Hello" for s in str: print(s) # H e l l o for t in range(5): print(t) i = 0 while i < len(str): print(str[i]) i+=1 ======================== Iterator: ========= ==> an object which enables the traversing on the collection like: list, tuple, dictionary etc. only one element at time. ==> to implement the iterator: two methods: 1) __iter__() 2) __next__() __iter__(): =========== ==> magical method ==> return the iterator object ==> which is point on the current element in collection ex: [1,2,3,4,5] __iter__() ==> current value = '1' __next__() ==> next value = 2 __next__(): =========== ==> return the next element/item in the collection Why the iterator object? ======================== to use the memory efficiently while handling the larger set of the data, iterator obect can use. Iterating Statements (Iterable) Vs Iterator: ============================================= for, while ==> from collection returning only one element at a time. str = "Hello" for s in str: print(s) # H e l l o iterator ==> can return stream of data print(iter("Python")) print(iter([1,2,3,4,5,6,7])) print(iter({})) # print(iter(100)) ================================== data = iter([1,3,5,7,9]) print(data) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) How to Handle the exception while using the iterator: ===================================================== d = iter(('abc','def','ghi','jkl','lmn')) print(next(d)) while True: try: # the code which want to make execute normally even with exception. n = next(d) print(n) except StopIteration: break ================================================== class myClass: def __init__(self, n): self.start = -1 self.end = n def __iter__(self): return self def __next__(self): if self.start < self.end - 1: self.start += 2 # start = start + 2 1 3 5 7 9 11 13 15 return self.start else: raise StopIteration obj = myClass(5) while True: try: t = next(obj) print(t) except StopIteration: break