Python Introduction

Variables

In Python, types of variables are automatically inferred by the interpreter

In [1]:
school = "Paul G. Allen School" # creates a variable of type str
number = 446       # int
pi = 3.141         # float

print("department:", school)
print("number:", number)
print("pi:", pi)

print(type(school), type(number), type(pi))
department: Paul G. Allen School
number: 446
pi: 3.141
<class 'str'> <class 'int'> <class 'float'>

Math operations

In [2]:
a = 13
b = 4

print(a + b)
print(a / b) # floating point division
print(a // b) # integer division
print(b**2) # powers are built-in
17
3.25
3
16

Conditionals

Python cares about whitespace! There are no brackets or end statements

Instead of &&, ||, !, we use 'and', 'or', and 'not'.

Boolean values are written as 'True' and 'False'

In [3]:
a = 9.1
b = 7

# basic if else syntax
if a < 10:
    print('hello there!')
else:
    print('general kenobi')

print('this always prints')
hello there!
this always prints
In [4]:
# and syntax
if a < 10 and b > 5:
    print('and')

# or syntax
if a > 10 or b > 5:
    print('or')
and
or
In [5]:
# else, else if syntax
if False:
    print('this never prints')
elif a != b:
    print('a != b')
else:
    print('else!')
a != b

Data Structures

In [6]:
# Lists
fruit = ['apple', 'pear', 'tomato', 'avocado']
print(fruit)
print(fruit[0])
print(fruit[-2]) # can use reverse indexing
print(fruit[1:3]) # can index multiple items [inclusive, exclusive)
fruit[3] = 'salmon' # can assign items in list

print(fruit)
['apple', 'pear', 'tomato', 'avocado']
apple
tomato
['pear', 'tomato']
['apple', 'pear', 'tomato', 'salmon']
In [7]:
print(len(fruit))
print('pear' in fruit) # can check for existence in a list ("contains()")
4
True
In [8]:
fruit.append('trout') # lists are mutable

print(fruit)
print(len(fruit))
['apple', 'pear', 'tomato', 'salmon', 'trout']
5
In [9]:
# tuples
tupperware = (1,2,3)
print(tupperware)
print(tupperware[1])
a, b, c = tupperware # can unpack tuples
_, d, _ = tupperware # ignore the elements you don't care about
print(c)
print(d)
(1, 2, 3)
2
3
2
In [10]:
tupperware[1] = 4 # cannot modify tuples
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-bc91c297afb1> in <module>()
----> 1 tupperware[1] = 4 # cannot modify tuples

TypeError: 'tuple' object does not support item assignment
In [11]:
# dicts (maps)
ages = {'Ben': 21, 'Newton': 84}
print(ages)
print(ages['Ben'])
ages['Einstein'] = 76
ages[5] = 'hi'
print(ages)
{'Ben': 21, 'Newton': 84}
21
{'Ben': 21, 'Newton': 84, 'Einstein': 76, 5: 'hi'}

Loops

In [12]:
# basic for loops
for i in range(5):
    print(i)
    
print()

# can loop over any iterable
for f in fruit:
    print(f)
0
1
2
3
4

apple
pear
tomato
salmon
trout
In [13]:
# advanced for loops
for idx, item in enumerate(fruit):
    print(idx, item)
    
print()

a = [3, 1, 4, 1, 5]
b = [2, 7, 1, 8, 2]

for f, pi, e in zip(fruit, a, b):
    print(f, pi, e)
0 apple
1 pear
2 tomato
3 salmon
4 trout

apple 3 2
pear 1 7
tomato 4 1
salmon 1 8
trout 5 2
In [14]:
# while loops
my_str = "Ben"

while len(my_str) < 10:
    my_str += ' 10'

print(my_str)
Ben 10 10 10

Functions + Classes

In [15]:
# this is a function
def square_this(x):
    return x * x

print(square_this(4))
16
In [16]:
class Squaring:
    
    # this is the constructor
    def __init__(self, a, b=4):
        self._a = a
        self._b = b
    
    # this is a method
    def square(self, x):
        return x * x
    
    # this is a static method
    @staticmethod
    def mymethod(x):
        return x**3

sq = Squaring(3)
print('method:', sq.square(3))
print('static method:', Squaring.mymethod(5))
print('a:', sq._a)
print('b:', sq._b)
method: 9
static method: 125
a: 3
b: 4

Numpy

Numpy is a powerful scientific computing library for Python. It uses C/C++ in the background to speed up computation

In [17]:
import numpy as np

a = np.array([1,2,3,4,5])
b = np.array([5,4,3,2,1])
c = a + b # can do elementwise operations
print(c)
print(a*b)
print(a[3:5]) # can use same indexing as lists
print(type(a))
[6 6 6 6 6]
[5 8 9 8 5]
[4 5]
<class 'numpy.ndarray'>
In [18]:
A = np.array([[1,2], [3,4]]) # can create multidimensional arrays
print(A)
print(A[0]) # indexing into rows
print(A[:,1]) # indexing into columns
print(A[1,1], A[1][1]) # indexing into rows and columns
print(A[:,1].T) 
print(np.shape(A[:,1]))
[[1 2]
 [3 4]]
[1 2]
[2 4]
4 4
[2 4]
(2,)
In [19]:
# can create special types of arrays
a = np.zeros((4,4))
b = np.ones(3)
c = np.random.random(5)
print(a)
print(b)
print(c)
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
[1. 1. 1.]
[0.74431292 0.7623311  0.84634447 0.63841964 0.89056371]
In [20]:
# matrices
A = np.array([[1,2],[3,4]])
B = np.array([[1, 0],[0, 1]]) # identity matrix (same as np.eye(2))

print(A + B)
print()
print(A @ B)#@ is matrix multiplication 
print(A * B)#* is elementwise multiplication. You probably don't mean this
[[2 2]
 [3 5]]

[[1 2]
 [3 4]]
[[1 0]
 [0 4]]
In [21]:
# numpy functions (see documentation for more)
A = np.array([[1,1],[2,2],[3,3]])
print(A)
print(np.sum(A)) # can sum all elements
print(np.sum(A, axis=0)) # can also sum along a dimension (0)
print(np.sum(A, axis=1)) # can also sum along a dimension (1)
[[1 1]
 [2 2]
 [3 3]]
12
[6 6]
[2 4 6]
In [22]:
# use numpy to speedup computation
# as a rule, use numpy operations to calculate things, not for loops.
# e.g. call np.dot don't sum over a for loop of the elements.
import time
n = 100000
a = np.ones(n)
b = np.ones(n)
start = time.time()

res = a + b

numpy_time = time.time() - start
print("time:", numpy_time)

res = []
start = time.time()

for i in range(n):
    res.append(a[i] + b[i])
    
loop_time = time.time() - start
print("time:", loop_time)

print("speedup x:", loop_time / numpy_time)
time: 0.0012447834014892578
time: 0.05220365524291992
speedup x: 41.93794292281172

Matplotlib

Matplotlib is a library used to visualize data

In [23]:
import matplotlib.pyplot as plt
In [24]:
# basic plotting (show scatter and plot)
xs = np.arange(10)
ys = xs ** 2
plt.scatter(xs, ys)
plt.plot(xs, ys)

# ALWAYS label your plots!
plt.title('plot of $x^2$ vs $x$')
plt.xlabel('$x$')
plt.ylabel('$x^2$')
plt.show()