4 Control and Loops
4.1 If Statement
4.2 For Loops
4.2.1 For .. Else Construct
else
is only executed when the for loop completed all cycles
= [1,2,3,4,5]
mylist
for i in mylist:
print (i)
else:
print('Hooray, the loop is completed successfully')
#:> 1
#:> 2
#:> 3
#:> 4
#:> 5
#:> Hooray, the loop is completed successfully
In below exmaple, for loop encountered break
, hence the else
section is not executed.
for i in mylist:
if i < 4:
print (i)
else:
print('Oops, I am breaking out half way in the loop')
break
else:
print('Hooray, the loop is completed successfully')
#:> 1
#:> 2
#:> 3
#:> Oops, I am breaking out half way in the loop
4.2.2 Loop thorugh ‘range’
for i in range (1,10,2):
print ('Odds Number : ',i)
#:> Odds Number : 1
#:> Odds Number : 3
#:> Odds Number : 5
#:> Odds Number : 7
#:> Odds Number : 9
4.2.3 Loop through ‘list’
4.2.3.1 Standard For Loop
= ['a','b','c','d']
letters for e in letters:
print ('Letter : ',e)
#:> Letter : a
#:> Letter : b
#:> Letter : c
#:> Letter : d
4.2.3.2 List Comprehension
Iterate through existing list, and build new list based on conditionnew_list = [expression(i) for i in old_list]
= ['abc','abcd','bcde','bcdee','cdefg']
s for x in s] [x.upper()
#:> ['ABC', 'ABCD', 'BCDE', 'BCDEE', 'CDEFG']
Extend list comprehension can be extended with if
condition**new_list = [expression(i) for i in old_list if filter(i)]
= ['abc','abcd','bcde','bcdee','cdefg']
old_list = [ x.upper() for x in old_list if 'bcd' in x ]
matching print( matching )
#:> ['ABCD', 'BCDE', 'BCDEE']
4.3 Generators
- Generator is lazy, produce items only if asked for, hence more memory efficient
- Generator is function with ‘yield’ instead of ‘return’
- Generator contains one or more yields statement
- When called, it returns an object (iterator) but does not start execution immediately
- Methods like iter() and next() are implemented automatically. So we can iterate through the items using next()
- Once the function yields, the function is paused and the control is transferred to the caller
- Local variables and their states are remembered between successive calls
- Finally, when the function terminates, StopIteration is raised automatically on further calls
4.3.1 Basic Generator Function
Below example give clear understanding of how generator works
def my_gen():
= 1
n print('This is printed first')
# Generator function contains yield statements
yield n
+= 1
n print('This is printed second')
yield n
+= 1
n print('This is printed at last')
yield n
= my_gen()
a type(a)
#:> <class 'generator'>
next(a)
#:> This is printed first
#:> 1
next(a)
#:> This is printed second
#:> 2
4.3.2 Useful Generator Fuction
Generator is only useful when it uses for-loop - for-loop within generator - for-loop to iterate through a generator
def rev_str(my_str):
= len(my_str)
length for i in range(length - 1,-1,-1):
yield my_str[i]
for c in rev_str("hello"):
print(c)
#:> o
#:> l
#:> l
#:> e
#:> h
4.3.3 Generator Expression
Use () to create an annonymous generator function
= [1, 3, 6, 10]
my_list = (x**2 for x in my_list) a
next(a)
#:> 1
next(a)
#:> 9
sum(a) # sum the power of 6,10
#:> 136
4.3.4 Compare to Iterator Class
class PowTwo:
def __init__(self, max = 0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n > self.max:
raise StopIteration
= 2 ** self.n
result self.n += 1
return result
Obviously, Generator is more concise and cleaner
def PowTwoGen(max = 0):
= 0
n while n < max:
yield 2 ** n
+= 1 n