<jupyter_start><jupyter_text>Control Flow and Doing things Repeatedly A big part of the draw of programming is the ability to have the computer do the boring repetitive stuff in our work. This lesson we will discuss and apply **for** loops and **while** loops to various problems. This lesson combines a lot of the concepts from previous lessons like making logical decisions and collections of data<jupyter_code># A list to work with
well_names = ['Big Bear', 'Endor', 'Tim', 'Tiny', 'Elsa']<jupyter_output><empty_output><jupyter_text>Let start simple and print each item in the list individually. The syntax is for (name_of_item_var) in collection<jupyter_code># in this case we are looping through each item in a list
for well_name in well_names:
    print(well_name) # Note the indentation, everything at this indent level is excuted within the loop<jupyter_output><empty_output><jupyter_text>We can iterate through numbers like this:<jupyter_code>for num in range(5):
    print(well_names[num])<jupyter_output><empty_output><jupyter_text>If we use the wrong number, this happens<jupyter_code>for num in range(6):
    print(well_names[num])<jupyter_output><empty_output><jupyter_text>We can automatically get the length of a list with len()<jupyter_code>for num in range(len(well_names)):
    print(well_names[num])
print(len(well_names))<jupyter_output><empty_output><jupyter_text>If we need number and the items in the collection we can use enumerate. Enumerate creates a tuple (remember those!?) that is the index and the well name. We can **unpack** the tuple by providing a variable for each value.<jupyter_code>for a_tuple in enumerate(well_names):
    print(a_tuple) # add the number to the well name

print('With tuple unpacking')

for num, well_name in enumerate(well_names):
    print( well_name + '_{}'.format(num)) # add the number to the well name<jupyter_output><empty_output><jupyter_text>We can also loop over dictionaries using .items()<jupyter_code>well_dictionary  = {'00000000100000' : 'Big Bear',
                    '00000000200000' : 'Endor',
                    '00000000300000' : 'Big Bear',
                    '00000000400000' : 'Tim',
                    '00000000500000' : 'Elsa',}
# Items creates a tuple
for item in well_dictionary.items():
    print(item)
# We can unpack the tuple by providing variables
for key, value in well_dictionary.items():
    print(key)
    print(value)<jupyter_output><empty_output><jupyter_text>**Challenge**: Can you use a for loop to correct all the keys and well names to reflect that they are re-drills? Now lets discuss while loops. While loops keep executing as long as a condition is true. This can be useful if you aren't iterating over a collection of objects, but want to execute code until an event occurs. At the core of most compute applications is a while loop that keep the programming running until either an error occurs and crashes the program or until the user decides to close it. Programmers call this the 'main' or application loop.<jupyter_code>counter = 1
while counter < 11: # remember this from if statements? It works pretty much the same way!
    print(counter)
    counter += 1
print('done counting!')<jupyter_output><empty_output><jupyter_text>While loops can be dangerous if misused in a program. If you set a condition on a while loop that will **never** be false then you have created an **infinite** loop. (Ctrl+Alt+Delete time for windows users). It is always wise to set constraints on while loops that could fail this way, just in case. **Break** statements can be used to exit for and while loops early and it pays to check for infinite loop conditions with if statements.<jupyter_code>counter = 1
while counter < 11: # remember this from if statements? It works pretty much the same way!
    print(counter)
    counter -= 1
    if counter < 0:
        print('this would be an infinite loop, I saved you!')
        break
print('done counting!')<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup