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 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.
#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 elif
s 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.
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.
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