0% found this document useful (0 votes)
3 views8 pages

Python Iterators and Generators

Uploaded by

venkychow222
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views8 pages

Python Iterators and Generators

Uploaded by

venkychow222
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Iteration

Iteration is a general term for taking each item of something, one after another. Any time you
use a loop, explicit or implicit, to go over a group of items, that is iteration.

In [1]: num = [1,2,3]

for i in num:
print(i)

1
2
3

Iterator
An iterator is an object that allows the programmer to traverse through a sequence of data
without having to store the entire data in the memory.

In [ ]: import sys
L = [x for x in range(1,10000000)]

print(len(L))
print(sys.getsizeof(L)/1024)
for i in L:
print(i*2)

In [ ]: L = [x for x in range(1,100000)]

for i in L:
print(i*2)
pass

import sys

sys.getsizeof(L)/1024

In [2]: import sys


x = range(1,10000000000) #iterator

for i in x:
print(i*2)
pass

print(sys.getsizeof(x)/1024)

print(x)

0.046875
range(1, 10000000000)

In [ ]: for i in x:
print()

Iterable
Iterable is an object, which one can iterate over.
It generates an iterator when passed to iter() method.

In [1]: L = [1,2,3]
print(type(L))

# L is an iterable
print(type(iter(L)))

<class 'list'>
<class 'list_iterator'>

Points to remember
1. Every Iterator is also an Iterable.
2. Not all Iterables are Iterators.
3. Every Iterable has an iter function.
4. Every Iterator has both iter function as well as a next function.

In [2]: a = 2

dir(a)
Out[2]: ['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__init_subclass__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
'as_integer_ratio',
'bit_count',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']

In [3]: #T = (1,2,3)
#T = {1,2,3}
T = {1:2,2:3}
dir(T)

Out[3]: ['__class__',
'__class_getitem__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__ior__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__ne__',
'__new__',
'__or__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__ror__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values']

In [4]: L = [1,2,3]
#L is not an iterator
dir(L)

Out[4]: ['__add__',
'__class__',
'__class_getitem__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__iadd__',
'__imul__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__rmul__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'append',
'clear',
'copy',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']

In [5]: x = iter(L)

dir(x)
Out[5]: ['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__length_hint__',
'__lt__',
'__ne__',
'__new__',
'__next__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setstate__',
'__sizeof__',
'__str__',
'__subclasshook__']

Understanding how for loop works


In [6]: num = [1,2,3] # iterable

for i in num:
print(i)

1
2
3

In [10]: num = [1,2,3]

# fetches the iterator


iter_num = iter(num)

# call next
print(next(iter_num))
print(next(iter_num))
print(next(iter_num))
next(iter_num)

1
2
3
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
Cell In [10], line 10
8 print(next(iter_num))
9 print(next(iter_num))
---> 10 next(iter_num)

StopIteration:
Making our own for loop
In [11]: def own_for(iterable):
iterator = iter(iterable)
while True:
try:
print(next(iterator))
except StopIteration:
break

In [16]: a = [1,2,3]
b = range(1,11)
c = (1,2,3)
d = {1,2,3}
e = {0:1,1:1}

own_for(e)

0
1

Confusion Point
In [17]: num = [1,2,3]
iter_obj = iter(num)

print('Address of iterator 1',id(iter_obj))

iter_obj2 = iter(iter_obj)
print('Address of iterator 2',id(iter_obj2))

Address of iterator 1 2489971767328


Address of iterator 2 2489971767328

Creating our own range() function


In [ ]: # iterable
class my_range:

def __init__(self,start,end):
self.start = start
self.end = end

def __iter__(self):
return my_range_iterator(self)

# iterator
class my_range_iterator:

def __init__(self,iterable_obj):
self.iterable = iterable_obj

def __iter__(self):
pass

def __next__(self):

if self.iterable.start >= self.iterable.end:


raise StopIteration
current = self.iterable.start
self.iterable.start += 1
return current

In [ ]: for i in my_range(1,11):
print(i)

In [ ]: x = my_range(1,11)
type(x)

What is a Generator
Python generators are a simple way of creating iterators.

In [ ]: import sys

L = [x for x in range(100000)]

#for i in L:
#print(i**2)

sys.getsizeof(L)

In [ ]: x = range(100000)

sys.getsizeof(x)

Simple Example of Generator


In [24]: def gen_demo():
yield "first statement"
yield "second statement"
yield "third statement"

In [25]: gen = gen_demo()


print(gen)

<generator object gen_demo at 0x00000243BE6344A0>

In [20]: for i in gen:


print(i)

first statement
second statement
third statement

In [26]: print(next(gen))
print(next(gen))
print(next(gen))

first statement
second statement
third statement

In [27]: print(next(gen))

You might also like