Python For Quantum Mechanics#

Week 2: Flow Control#

from IPython.display import YouTubeVideo
YouTubeVideo('6IUQ12mOb1A',width=700, height=400)

Contents#

If Statments#

We often require the execution certain code under specific conditions. For example there is a simple if statement that executes if the condition is satisfied.

If condition

if 1 < 4:
    print('1 is less than 4')

if 1 > 4:
    print('1 is greater than 4')
1 is less than 4

Make note also of the indentation as it is not just decoration, it is used by Python to seperate blocks of code.

There is a more complicated version where there are different parts of the code that execute under particular conditions. For example if x is true then do y, otherwise (else) do z. This is encapsulated in the if, elif (else if), and else statements.

if,elif else

#Feel free to experiment with the boolean value of the following condtions
Condition1 = False
Condition2 = True
a=1
b=2


#Notice the indented blocks of code, this indicates which code to be executed under the stated conditions

if Condition1: #If condition1 is true
    a=a+b #do this

elif Condition2:#Else if condition2 is true
    a=a-b #do this

else: #else if both conditions are false
    a=a*b #do this

print(a)
-1

We can also nest conditional statements

Condition1 = True
Condition2 = False

if Condition1:
    if Condition2:
        print("Both conditions are TRUE")
    else:
        print("Condition1 is TRUE, Condition2 is FALSE")
elif Condition2:
    print("Condition1 is FALSE, Condition2 is TRUE")
else:
    print("Both conditions are FALSE")
Condition1 is TRUE, Condition2 is FALSE

Or the following does the same

if Condition1 and Condition2:
    print("Both conditions are TRUE")
elif Condition1 and not Condition2:
    print("Condition1 is TRUE, Condition2 is FALSE")
elif Condition2:
    print("Condition1 is FALSE, Condition2 is TRUE")
else:
    print("Both conditions are FALSE")
Condition1 is TRUE, Condition2 is FALSE

As does

if Condition1 and Condition2:
    print("Both conditions are TRUE")

if Condition1 and not Condition2:
    print("Condition1 is TRUE, Condition2 is FALSE")
    
if not Condition1 and Condition2:
    print("Condition1 is FALSE, Condition2 is TRUE")
    
if not Condition1 and not Condition2:
    print("Both conditions are FALSE")
Condition1 is TRUE, Condition2 is FALSE

It should be noted that we can ommit either/both elif and else as well as having as many elifs as we want.

Try and Except#

Testing code is an import way to find out where the problems are. The try-except

try: # block of code...
    print(hi) # this should be a string, otherwise we are calling a variable name that hasn't be assigned a value so a NameError will be given.
    y = (1/0,5,7) # notice the 1/0 is not possible to compute and therefore a ZeroDivisionError error will be given
    y[2] = 2 # y is a tupple wich cannot be changed so we will get a TypeError
    
except NameError: # executes variable's (or other object's) name is invalid
    print('there was a name error')

except ZeroDivisionError: # executes when a division by 0 is found
    print('there is division by 0')
    
except TypeError: # if we try to do something with a type that doesn't have that functionality
    print('there was a type error')

except : # executes when a differnt problem found
    print('there is a different problem')

else: # executes when no problem found
    print('no problem found')

finally: # executes regardless of problem when block of code is finished
    print('code is finished')
there was a name error
code is finished

While Loops#

While loops will continuously execute a block of code so long as the condition upon which they depend is satisfied.

While loop

x=0
y=1

while x<100:
    print(x)
    x,y = y,x+y
0
1
1
2
3
5
8
13
21
34
55
89

Range and Zip#

The range class is very useful for loops as we will see next. Lets explore it, and see how we can use lists to visualise it.

stop = 10
x = range(stop)
print(type(x))
print(x)
#Now lets cast to a list and print so we can see what this looks like

x = list(x)

print(x)
<class 'range'>
range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Notice that we get a sequence running from 0-9, not 0-10!! It turns out we can add arguments in the parantheses to obtain a more specific sequence:

start = 10
stop = 40
step = 2

x = range(start, stop, step)

#We see range iterates from start to stop in increments of size step
print(list(range(start, stop, step)))
[10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38]

We see range iterates from start to stop - 1 in increments of size step.

It is useful to note the default vales of range(). If not given start is defaulted to 0 and step to 1.

print(list(range(10))) # if only one argument is given it is taken as "stop"

print(list(range(3,9))) # if two arguments are given it is taken as "start" and "stop"
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 4, 5, 6, 7, 8]

The zip() function takes in two iterable data structures and returns an iterator of two object tupples as shown.

a = [1,2,3,4] # doesn't matter if these are tuples or lists
b = ('one', 'two', 'three')

c = zip(a,b)

print(type(c))

print(tuple(c)) # we can't directly print zip type objects so we cast them into a 
#tuple (or list) to see their contents
<class 'zip'>
((1, 'one'), (2, 'two'), (3, 'three'))

Each item is paired with its corresponding item in the structures. The length of this new object is determined by the shortest list as seen. This is a very useful object when we iterate over two objects.

For Loops#

Loops are useful for iterable processes, which are very common in the programming world. Here we illustrate the use of a for loop which is used together with iterable objects like lists.

For loop

L = [2,4,5,6,7,11,24,6]

for i in L:
    print(i)
2
4
5
6
7
11
24
6

We saw the range function before, which is very useful when combined with loops

#The Fibonacci Sequence:
x=0
y=1


for i in range(1,20):
    print('Fib',i,':',x)
    x,y = y,x+y
Fib 1 : 0
Fib 2 : 1
Fib 3 : 1
Fib 4 : 2
Fib 5 : 3
Fib 6 : 5
Fib 7 : 8
Fib 8 : 13
Fib 9 : 21
Fib 10 : 34
Fib 11 : 55
Fib 12 : 89
Fib 13 : 144
Fib 14 : 233
Fib 15 : 377
Fib 16 : 610
Fib 17 : 987
Fib 18 : 1597
Fib 19 : 2584

Sometimes we want to use both the placement of an object and the object itself. For this the enumerate() function is useful

words = ('first', 'second', 'third')

for i, word in enumerate(words): # notice the two 
    print(i,word)
0 first
1 second
2 third

We can also iterate over two objects using zip()

a = [1,2,3,4] 
b = ('one', 'two', 'three')

for i,j in zip(a,b):
    print(i, j)
1 one
2 two
3 three

or using dictionaries, the keys will be iterated over. The .items attribute will allow you to iterate over both the keys and the values in a similar way to zip().

QM_Constants = {
    'planck' : 6.62607015e-34,
    'speed of light' : 299792458,
    'pi' : 3.14159265359}

for i in QM_Constants: # will iterate over keys of the dictionary
    print(i,'->',QM_Constants[i])

print('\n')

for i,j in QM_Constants.items(): # .items() makes the dictionary an iterator of two object tuples
    print(i,'->',j)
planck -> 6.62607015e-34
speed of light -> 299792458
pi -> 3.14159265359


planck -> 6.62607015e-34
speed of light -> 299792458
pi -> 3.14159265359

Break, Continue, Pass#

Using break stops a loop.

i = 0

while i==i:
    print(i)
    i=i+1
    if i>5:
        print("Uh oh! STOP!")
        break # Stops a loop
    print("I'm still iterating")
0
I'm still iterating
1
I'm still iterating
2
I'm still iterating
3
I'm still iterating
4
I'm still iterating
5
Uh oh! STOP!

Using continue skips the rest of the code in that iteration of the loop and imediately moves onto the next.

for i in range(10):
    print(i)
    if i>=5:
        continue # Moves us to the next iteration in the loop and ignores any code that follows
    print("i is less than 5")
0
i is less than 5
1
i is less than 5
2
i is less than 5
3
i is less than 5
4
i is less than 5
5
6
7
8
9

The main function of pass is to fulfill a syntactical requirement; that is that something is required in a claus (bit of indented code after a colon (:). Often a useful placeholder that still alows for code to function when incomplete.

i=0

while i<10:
    print(i)
    i=i+1
    if i>5:
        pass # pass just moves on to the following code
0
1
2
3
4
5
6
7
8
9