This notebook will contain brief notes on topics covered in the course.
There are many different classes of objects in Python. We will not cover all of them here. Below is a short list of some of the basic objects (datatypes) we will commonly use:
int: Integers like ...,-2, -1, 0, 1, 2....
There is a limit to how large these can be and you must be careful about what happens when you use division.
float: Floating point numbers have a decimal part like 2.1
and 3.000023
. Because the computer uses binary to represent numbers, not every number can be perfectly represented by a float.
bool: Boolean variables are either True
or False
and can be used to compare other data types.
list: A list is an ordered collection of objects. These are typically used if you need to repeat a procedure. For example [1,2,3,5]
is a list. Note: lists use square brackets and can contain different data types.
string: A string is essentially a list of characters. For example, 'python'
is a string. Note: the int 1
is different from the char '1'
.
You can figure out an objects type by using the type()
function.
type(1)
type(3.2)
type(True)
type([1,2,3])
type('3')
Operators allow you to take data types and manipulate their values. The same symbol may do different things depending on the data types used as inputs. Expressions are just how we tell the computer what we would like it to do.
3 + 4
3 / 2
[1,2,3] + [4,5,6]
'python' + ' ' + 'is great'
3 + 4 * 2
Comparisons are expressions that usually evaluate to True
or False
. We use these when writing code that reacts to a given input.
3 <= 4
'Hello' == 'hello'
Variables act as a storage or placeholder for different data types that allows us to write abstract code that can handle a unknown input values. Variable names are case sensitive and cannot begin with a number. There are a few other rules regarding variable names. As the scope of your project grows, make sure to use long, descriptive variable names to help. Note that =
is different from ==
. In particular, =
assigns the value on the right to the variable on the left, while ==
returns a boolean value when comparing the objects on the right and left.
x = 2
x + 3
x = x + 1
x
y = x
y
y == x
Functions are helpful in that they allow you to write code that can be easily reused. Instead of writing the same block of code multiple times in a program (if needed), use a function. Note that in Python, whitespace is critical. Indented lines are considered to be part of the function, while lines that line up with the function definition line do not.
The basic structure is:
def function_name(input_variable1, input_variable2,...):
code
return output
def square(n): return n*n
square(3)
square(5.1)
If/Elif/Else statements are useful whenever we need a program that reacts to some input. Note the importance of whitespace here as well. For example, the absolute value function is defined as $|x|=\begin{cases}\phantom{-}x & \text{ if $x\geq 0$}\\-x & \text{ otherwise.}\end{cases}$
The basic structure is:
if comparison:
code1
else:
code2
If the comparison is true, code1
executes. Otherwise, code2
executes. If more than two options are needed, use elif
with additional comparisons.
if comparison1:
code1
elif comparison2:
code2
else:
code3
x = -3 if x >= 0: print(x) else: print(-x)
Lists and strings are very similar and share a lot of similar behavior/operators. When assigning a list or string to a variable, we can extract portions of the list of string using indexing. Remember that Python is zero indexed. Negative numbers may be used to select items counting from right to left rather thant he usual left to right.
my_list = [1,5,7,3,9] my_string = 'quick'
my_list[0]
my_string[-1]
Lists and strings allow for slicing, which produces a copy of the list or string containing the subset of elements listed.
The usual notation is:
variable_name[start:stop + 1: step_size]
Blanks may be used for the start and stop portion to indicate that you want to start from the beginning or go to the very end. A negative step size reverses the direction of the list or string.
my_list[2:4]
my_string[:3]
my_list[::2]
my_list[::-1]
While loops are useful when you need to repeat some procedure but are not sure of how many iterations will be needed. In many situations, while and for loops are interchangable.
The basic structure is:
while comparison:
code
The code inside the while loop will continue to be executed until the comparison is false. That means it is up to you to update the variables associated with the comparison unless you want a loop that either never runs or runs forever.
n = 1 while n <= 10: print(n) n += 1
A for loop is useful when you you would like to compute something repeatedly based on each element in a list, string, or other iterable.
The basic structure is:
for variable in iterable:
code
If your iterable is a list of numbers or a string, then we can perform a common operation based on each individual element in the list or string.
for x in [1,2,3,4,5]: print(-x)
for c in 'Hello there!': print(c)
The following example combines the length function with string indexing. It accomplishes the same thing as the previous loop.
s = 'Hello there!' for i in range(len(s)): print(s[i])
for x in my_list: print(1/x)
for y in my_string: print(y.upper())
The basic formula for compound interest:
$P'=P\cdot\left(1+\frac{r}{n}\right)+c$
$P =$ principal
$r =$ annual interest rate
$n =$ number of compoundings per year
$c =$ contribution for principal per compounding period
$P' =$ new principal after one compounding period
Recursion involves objects whose definitions refer to themselves.
Recursion is useful when solving a problem whose solution involves first solving a “smaller” version of the same problem.
Recursive definitions involve two key ingredients:
Below we give a recursive definition of the function that computes the minimum number of moves needed to solve the Tower of Hanoi problem with $n$ discs.
def hanoi(n): if n == 1: return 1 else: return 2*hanoi(n-1)+1 hanoi(7)
A list comprehension if a shortcut that allows you to create lists of elements using notation similar to set-builder notation.
The basic structure is:
[expression(var) for var in iterable if condition]
This is equivalent to:
L = []
for var in iterable:
if condition:
L.append(expression(var))
The list comprehension below contains the set of odd cubes from 0 to 1000.
[x**3 for x in range(10) if x%2==1]
We will use the Matplotlib library for basic plotting. Matplotlib is not available by default in Python and must be imported. The general idea is that you issue various commands that modify a plot until you are satisfied with the results. There are a wide variety of options. The recommendation is that you use the Matplotlib website for help. Do not attempt to memorize all of Matplotlib.
import matplotlib.pyplot as plt x = [1,2,3] y1 = [3,5,2] y2 = [-3,2,5] plt.scatter(x,y1,color='red',label='y_1') plt.scatter(x,y2,label='y_2') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.title('y vs. x')
We use the Bisection Method to estimate the roots of a continuous function $f(x)$. This is done in the following way:
def bisection(a,b,f,err): c = (a+b)/2 while c-a > err: if f(c) == 0: return n elif f(c)*f(a) > 0: a = c else: b = c c = (a+b)/2 return c def root2(n): return n*n-2 bisection(0,2,root2,0.0001)
Newton's Method is an alternative method for finding roots of differentiable functions. While it may converge faster than the Bisection Method algorithm, it is not always guaranteed to converge. Newton's Method uses the following recurrence relation to approximate roots of $f(x)$ $x_{n+1} = x_n-\dfrac{f(x_n)}{f'(x_n)}.$
def newton(f,df,x,n,err): i = 0 while abs(f(x)) > err and i <= n: x = x - f(x)/df(x) i += 1 if i > n: return False else: return x
To generate random numbers, use np.random
. The documentation covers most basic needs. Be sure to import the numpy
module.
We give a few examples below.
import numpy as np
Generating 10 random coin flips.
np.random.randint(0,2,size=10)
Selecting (with replacement) from a desired list.
myList = [1,2,3,5] np.random.choice(myList,size=20)
Shuffling a list.
myList2 = [1,2,3,4,5] np.random.shuffle(myList2) myList2
Below we have a few examples of how to manipulate an image by treating it as a matrix using the NumPy module. In this case our image is represented as a 3D matrix where the 1st entry represents the row number, the 2nd entry represents the column number, and the 3rd entry contains the red, green, blue (RGB) information as a number from 0-255 for each color.
import numpy as np import matplotlib.pyplot as plt
Importing an image.
image = plt.imread('galaxy.jpg')
The original image.
plt.imshow(image)