# Iteration in python (loops) This note explains and have exercises on loops while and for. For using this is suposed to be known by the student [Flow control in python](/zX6YpspsTnCvqmZC0vTzRg) and [Lists in python](/RWrVgWBOTOebitrb0MSFVw). :::info This is a note part of the coding course for IB Computer Science program. If you want to check out other parts of the same course you can see them in [This link of teaching material](/68GDv_RgT-yh9oERMvdnFw) ::: :::warning :warning: Note still under construction :warning: ::: ## While While is a keyword that is going to repeat the next indented block of instructions while a condition is met. The structure is this. ```python!= while condition: #what is expeted to be repeated pass ``` ### Infinite loop You can create an infinite loop doing something like this: ```python!= while True: pass ``` Other versions ```python!= while not False: pass ``` ```python!= while 4==2+2: pass ``` ### Make a loop a certain number of passes Imagine that we want to do something 300 times, we can create a variable to remember the number of times that we want to do something and update it every loop. For example, let's print the first 300 numbers ```python!= x = 1 while x <= 300 print(x) x+=1 ``` :::info Remember to update the variable if needed not to finish in a infinite loop ::: ### Use a while to find something We use what is called a **flag variable**. ```python!= found = False while not found: #the code for searching. ``` In this case is important that once we found whatever we're looking for we change the flag variable. If we don't we're creating an infinite loop. ### Thresholds Thresholds are limits. Limits for databases. We will need also a counter variable that saves if we're on the limit or not. Remember that this can be called whatever name is appropiate in the context. ```python!= threshold = 5 #limit value, can be hardcoded in the while or written as a variable. counter = 0 while counter < threshold: #the that we're going to operate. if someCondition: counter+=1 #if some condition the counter is going to add update ``` ### Case of the images of the pangolin This kind of threshold is used when looking for databases. For example, when we look for images of a pangolin, google have LOTS of images of a pangolin ![image](https://hackmd.io/_uploads/SkZvLlfZWl.png) But it's not going to return us all of them, just a few. That can be a threshold. ```python!= threshold = 50 #number of images that we can load images = 0 #number of images of pangolins while images < threshold: loadPangolin() images +=1 ``` Probably the pangolins are going to be added to a list. So instead of having a specific counter variable, we can use the length (len()) of the list as the counter. ```python!= threshold = 50 #number of images that we can load images = [] while len(images) < threshold: images.append(loadPangolin()) ``` We can also use while for traversing lists, but it's not recommended usually. It's very easy to forget to update the counter. ```python!= myList= ["Pipo", "Pepa", "Pepe", "Thomas Jefferson"] index = 0 while index < len(myList): # do something print(myList[index]) #update index index +=1 ``` Compare with the previous version with the for loop. This can be handly when dealing with PARALLEL LISTS ```python!= names = ["Pipo", "Pepa", "Pepe", "Thomas Jefferson"] grades = [7, 7, 4, 7] while index < len(names): #do something print(names[index], grades[index]) #update index index +=1 ``` We can do things like printing just the names who didn't get a 7 in their graides ```python!= names = ["Pipo", "Pepa", "Pepe", "Thomas Jefferson"] grades = [7, 7, 4, 7] while index < len(names): if grades[index] < 7: print(names[index]+ "didn't get a 7, they got a "+ grades[index]) #update index outside of the if index +=1 ``` For this we can also use zip https://ellibrodepython.com/zip-python ## For Loop for as seen in the list lesson is going to go over the elements in an _iterable_. So they go `for` elements `in` iterable. In many cases we use the list or other iterable and others a range of numbers. ```python!= for x in range(1,11): print(x*x) ``` ## Pass, continue, break ### Pass Pass is an empty instruction. It is used because all loops (or anything that has a colon `:` at the end such as [Functions](/Apsl9c53SSKET1Mlj7iM2Q) or classes) need at least one instruction and you may add it later. Example ```python!= for x in range(2,482,2): pass ``` In an exam you are unlikely to see or use it but is very common in some examples. ### Continue Continue is going to skip the rest of the instructions and go for other element of the loop Consider this loop: ```python!= for x in range(100): if x % 2 == 0: print(x) if x % 3 == 0: print(x) ``` It will print all the numbers that are either even or multipliers of 3. But the ones that are both of them they are going to get printed twice. ![image](https://hackmd.io/_uploads/r1NPDs7B-g.png) So for that, some of them they shouldn't be repeated. We add in the line 4 a `continue` so when arrives to that it doesn't ask the second if. ```python!= for x in range(100): if x % 2 == 0: print(x) continue if x % 3 == 0: print(x) ``` This will be the output ![image](https://hackmd.io/_uploads/B1WZ_oXrbg.png) (yeah, I know that there are other solutions for this like using or operators) This is a command tipicaly used in optimization of programs. ### Break Break is a command that is going to stop the inner loop right away. It is used to exit loops that should continue over until something happens (like when you're in a level in a game and you either win or lose that level) but also very common in finding stuff. Once you find $theThing you should stop the loop of "looking for $theThing" Let's do a trivial example, let's try to find the number `5` in `range(10)` ```python!= for x in range(10): print(x) #This is for debugging if x == 5: print("Found!") break ``` This will be the output ![image](https://hackmd.io/_uploads/BkLHYj7Hbg.png) But if we don't write the break sentence... ```python!= for x in range(10): print(x) #This is for debugging if x == 5: print("Found!") ``` this will be the output ![image](https://hackmd.io/_uploads/BkOOKoXr-l.png) Finding it will not terminate the loop. The most common example will look like this (this is an abstraction with also a flag variable) ```python!= found=False #flagVariable for x in iterable: if x.isWhatWeReLookingFor: found=True break if found: doWhateverWeWantToDoIfFound() else: doWhateverWeWantToDoIfNOTFound() ``` #### More in detail: Break and return We saw the `return` statement in [Functions in Python](/Apsl9c53SSKET1Mlj7iM2Q). You cannot write a return statement outside a function If we write this: :::danger it will output this: ```python!= for x in range(10): print(x) #This is for debugging if x == 5: print("Found!") return ``` It won't run and it will give us this error. ![image](https://hackmd.io/_uploads/S1pkcjQHWe.png) ::: But **if you're using a function and inside the loop you have a return statement, it will automatically end also the loop.** For example: ```python!= def findFive(): for x in range(10): print(x) #This is for debugging if x == 5: print("Found!") return ``` Will work as expected. Remember also that return can return also a value depending on the case. More on that in the [Functions in Python](/Apsl9c53SSKET1Mlj7iM2Q) ## Nested loops A nested loop is a loop inside another loop. Useful for sorting but also for 2D lists. [ 2D Lists in python](/-ylq-DUoTKOS6qGCiq3JRA) ```python!= for x in range(0,10): for y in range(0,10): print(10*x+y) ``` ```python!= for x in range(0,10): print("outer loop starts") for y in range(0,10): print("inner loop", end= " ") print(10*x+y) ```