Chapter 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
mylist = [1,2,3,4,5]
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
letters = ['a','b','c','d']
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 condition
new_list = [expression(i) for i in old_list]
s = ['abc','abcd','bcde','bcdee','cdefg']
[x.upper() for x in s]## ['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)]
old_list = ['abc','abcd','bcde','bcdee','cdefg']
matching = [ x.upper() for x in old_list if 'bcd' in x ]
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():
n = 1
print('This is printed first')
# Generator function contains yield statements
yield n
n += 1
print('This is printed second')
yield n
n += 1
print('This is printed at last')
yield na = my_gen()
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):
length = len(my_str)
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
my_list = [1, 3, 6, 10]
a = (x**2 for x in my_list)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
result = 2 ** self.n
self.n += 1
return resultObviously, Generator is more concise and cleaner
def PowTwoGen(max = 0):
n = 0
while n < max:
yield 2 ** n
n += 1