Strings, variable scope, exceptions
Working with strings
A string
object in Python has a number of built-in methods:
= "HSS Winter Series"
event <hit TAB once or twice> # strings can access a number of methods = functions
event.
event.capitalize()"S")
event.count("S") # the first occurrence
event.find("hello") # -1 = not found
event.find(= event.replace("HSS", "Humanities and Social Sciences")
event += " 2024"
event
event.lower() event.upper()
We can do all of this manipulation in one line:
= "HSS Winter Series"
event "HSS", "Humanities and Social Sciences")+" 2024").upper() (event.replace(
At this point you might ask about finding all occurrences of “S” inside events
. One possible solution:
import re # regular expressions library
for m in re.finditer("S", event)] # [1, 2, 11] [m.start()
Let’s now split our string:
= event.split() # split into words
words '_'.join(words) # join these words into a string with the `-` separator
This .join()
syntax is useful for many purposes, e.g. you can use it to convert a list to a string:
= ["Good", "morning"]
sentence str(sentence) # this is not what we want ...
" ".join(sentence) # this works!
Variable scope
The scope of a variable is the part of a program that can see that variable.
= 5
a def adjust(b):
sum = a + b
return sum
10) # what will the outcome be? adjust(
a
is the global variable ⇨ visible everywhereb
andsum
are local variables ⇨ visible only inside the function
Inside a function we can access methods of global variables:
= []
a def add():
5) # modify global `a`
a.append(
add()print(a) # [5]
However, from a local scope we cannot assign to a global variable directly:
= []
a def add():
= [1,2,3] # this will create a local copy of `a` inside the function
a print(a) # [1,2,3]
add()print(a) # []
Handling exceptions
Putting some explicit logic into your code to deal with errors will make your code more robust. For example, if the input data are missing, you can have some printout to show the instructions to get the data at runtime.
This error handling can be applied to calculations too. Let’s say we want to write a code to calculate mortgage payments. For a fixed interest rate in percent, we have two of the following three variables: (1) the principal amount, (2) the term in years, or (3) a monthly payment. Our code will calculate the third variable, based on the other two. There are three scenarios:
- If we have the principal amount and the term in years, here is how you would calculate the monthly payment:
= rate / 1200
r = (1 + r)**(12*term)
q = principal * r * q / (q - 1) payment
- If we have the monthly payment and the principal amount, here is how you would calculate the term in years:
= rate / 1200
r = payment / (payment - principal * r)
q if q < 0.:
print("you will never pay it off ...")
1)
exit(= log(q) / (log(1+r)*12) term
- If we have the term in years and the monthly payment, here is how you would calculate the principal amount:
= rate / 1200
r = (1 + r)**(12*term)
q = payment * (q - 1) / (r * q) principal
How can we tell the code to decide on the fly which variable it needs to compute, based on the two existing ones?
We would like to do something like this (not actual Python code):
if payment is not defined:
1
use formula if term is not defined:
2
use formula if principal is not defined:
3 use formula
Consider this syntax:
try:
# here is what we try to do
someUndefinedVariable except NameError:
= 1 # if that produces NameError, don't show it, but do this instead
someUndefinedVariable print(someUndefinedVariable)
And you can combine multiple error codes, e.g.
...except (RuntimeError, TypeError, NameError):
...
Write the rest of the mortgage calculation code.
You can also implement this code setting payment = None
for a missing variable, and then placing the code under if payment == None
condition. Alternatively, you can put everything into a function with optional arguments that default to None unless assigned values. I personally like the implementation with the exception handling, as this way you don’t have to assign the missing variable at all.
Number crunching in Python: if we have time
- How would you explain the following:
1 + 2 == 3 # returns True (makes sense!)
0.1 + 0.2 == 0.3 # returns False -- be aware of this when you use conditionals
abs(0.1+0.2 - 0.3) < 1.e-8 # compare floats for almost equality
import numpy as np
0.1+0.2, 0.3, atol=1e-8) np.isclose(
0.1 in binary will be 0.0001(1001) which we then truncate with round-off, then perform arithmetic, then convert back to decimal with round-off.
Write a code to solve \(x^3+4x^2-10=0\) with a bisection method in the interval \([1.3, 1.4]\) with tolerance \(10^{-8}\).