0% found this document useful (0 votes)
1 views

Week 3

ucl

Uploaded by

ran ju
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Week 3

ucl

Uploaded by

ran ju
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

MATH0011 Python L2

Week 3 assessed exercise due Monday 10:00


Week 2 assessed exercise will be re-graded
You must fix the file Assessed Exercises/Week 2/Week 2 assessed
exercise.ipynb
Python group project
Form a group of 3 or 4 people. I can help find groups.
Chooses one of the project notebooks on CoCalc.
Submit on Moodle by 6pm Friday 23rd February.
15% of your overall MATH0011 mark.
Read the project instructions.
Dictionaries
Dictionaries let us assign a value d[k] to a key k , just as a mathematical
function assigns a value to an input .
A dictionary is a bit like a list with arbitrary Python objects as indices.
(OK, almost arbitrary.)
Dictionary syntax
In [ ]: d = {} # create an empty dictionary
d[1] = "hello" # make key 1 have value "hello"
d[1] # get the value for the key 1

In [ ]: # creating a non-empty dictionary


atomic_numbers = {"hydrogen": 1, "magnesium": 13, "oxygen": 8}
atomic_numbers["tin"] = 50 # dictionaries are mutable. You can a
atomic_numbers["magnesium"] = 12 # ...and modify existing values
Using dictionaries
You can check if a dictionary has an entry for a particular key with in

In [14]: atomic_numbers = {"hydrogen": 1, "magnesium": 12, "oxygen": 8}


"oxygen" in atomic_numbers

Out[14]: True

Sometimes it is useful to do a for loop over a dictionary's keys and values.


d.items() produces all the (key, value) tuples in d .

In [15]: for pair in atomic_numbers.items():


print(pair[0], "has atomic number", pair[1])

hydrogen has atomic number 1


magnesium has atomic number 12
oxygen has atomic number 8
Which types can be dictionary keys?
In [16]: d = {}
d[(1, 2)] = 3

In [17]: d[[1, 2]] = 3

----------------------------------------------------------------
-----------
TypeError Traceback (most recent
call last)
Cell In [17], line 1
----> 1 d[[1, 2]] = 3

TypeError: unhashable type: 'list'

Dictionary keys must be "hashable types."

Numbers, strings, and tuples of immutable objects are hashable.


Mutable objects like lists or dictionaries are not hashable.
Why dictionaries?
Efficiency.

Checking if a number belongs to a list takes time proportional to the length of the
list.
Checking if a number is a dictionary key takes a constant amount of time,
independent of the number of keys.

Convenience.

Dictionaries let us express key-value associations in a natural and readable way.


Error handling
In [19]: def average_finder(data):
return [sum(d) / len(d) for d in data]

In [20]: average_finder([[1, 2, 3], [10, -10]])

Out[20]: [2.0, 0.0]

In [21]: average_finder([[1, 2, 3], [10, -10], []])

----------------------------------------------------------------
-----------
ZeroDivisionError Traceback (most recent
call last)
Cell In [21], line 1
----> 1 average_finder([[1, 2, 3], [10, -10], []])

Cell In [19], line 2, in average_finder(data)


1 def average_finder(data):
----> 2 return [sum(d) / len(d) for d in data]

Cell In [19], line 2, in <listcomp>(.0)


1 def average_finder(data):
----> 2 return [sum(d) / len(d) for d in data]
ZeroDivisionError: division by zero
Exceptions
When an error occurs, Python creates an Exception object.
We can use this to get information on the error and fix it.
To do this, we must use try and except .

In [22]: l = []
try:
mean = sum(l) / len(l)
except Exception as e:
print("something went wrong")
print("reason:", e)
mean = 0
print(mean)

something went wrong


reason: division by zero
0

In [23]: def add(x, y):


try:
return x + y
except TypeError as e:
print("I can't add those things.")
print(e)
add(1, "two")
I can't add those things.
unsupported operand type(s) for +: 'int' and 'str'
Raising your own exceptions
In [24]: def divide(x, y):
if y == 0:
raise Exception("Division by 0 isn't allowed.")
return x / y

In [25]: divide(2, 0)

----------------------------------------------------------------
-----------
Exception Traceback (most recent
call last)
Cell In [25], line 1
----> 1 divide(2, 0)

Cell In [24], line 3, in divide(x, y)


1 def divide(x, y):
2 if y == 0:
----> 3 raise Exception("Division by 0 isn't allowed.")
4 return x / y

Exception: Division by 0 isn't allowed.


Modules and import
import <modulename> lets you use functions and objects from
<modulename> via modulename.object
You only need to do it once per notebook

In [ ]: import math
math.sin(math.pi / 2)

There are lots of variants on this syntax.

import math as m lets you use m.sin in place of math.sin


from math import sin, cos lets you use sin and cos without the dot

In [29]: from random import randint


randint(1, 6) # random integer between 1 and 6 *inclusive*

Out[29]: 2
import numpy as np
What is NumPy for?
"The fundamental package for scientific computing with Python"
Used for all kind of numerical computation, principally numerical linear algebra.
Widely used in science and industry
NumPy arrays
Represent lists, vectors/matrices, higher-dimensional analogues.
Similar to Python lists, but with methods for numerical linear algebra.

1-D arrays are created using a list of their elements.

In [ ]: import numpy as np
a = np.array([1, 2, 3])
a.shape # (3, ), which is a tuple of length 1

2-D arrays are created using a list of rows.

In [30]: a = np.array([[1, 2], [3, 4]]) # shape (2, 2)


print(a)

[[1 2]
[3 4]]
Accessing array elements
Similar to Python list accesses.

In [ ]: a = np.array([1, 2, 3])
a[0]

In [31]: A = np.array([[1, 2], [3, 4]])


A[0] # 0th row of A

Out[31]: array([1, 2])

In [32]: A[0, 1] # A[0][1] is OK too

Out[32]: 2

In [33]: a[0] = 99 # arrays are mutable


a

Out[33]: array([[99, 99],


[ 3, 4]])
Addition and scalar multiplication
In [34]: a = np.array([[1], [-2]])

In [35]: 2 * a

Out[35]: array([[ 2],


[-4]])

In [36]: a + np.array([[-1], [2]])

Out[36]: array([[0],
[0]])

In [37]: a + 3 # this is "broadcasting"

Out[37]: array([[4],
[1]])
Array equality
In [38]: v = np.array([[1], [2]]) # 2x1 column vector
u = np.array([[1], [3]])
v == u

Out[38]: array([[ True],


[False]])

In [39]: np.array_equal(v, u)

Out[39]: False
Matrix multiplication
Use @ to matrix multiply arrays.

In [40]: A = np.array([[1, 1], [1, 1]])


A @ v

Out[40]: array([[3],
[3]])

In [41]: v @ A

----------------------------------------------------------------
-----------
ValueError Traceback (most recent
call last)
Cell In [41], line 1
----> 1 v @ A

ValueError: matmul: Input operand 1 has a mismatch in its core d


imension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2
is different from 1)

In [ ]: v + u # matrix/vector addition
Vectorizing
NumPy has its own version of functions like sin, cos, exp...

In [ ]: np.sin(np.pi) # not zero, but VERY small

In [ ]: a = np.array([np.pi, 0.5 * np.pi, -np.pi])


np.sin(a)

In [ ]: import math
math.sin(a)
Use import matplotlib.pyplot as plt for simple plots.
Simple matplotlib plots
plt.plot(xs, ys) plots the points with coordinates (xs[0], ys[0]) , (xs[1],
ys[1]) , ... and joins them with straight lines.

In [ ]: import matplotlib.pyplot as plt


plt.plot([0, 1], [1, 0])
Graphs of functions
np.linspace(a, b, N) produces N equally spaced points starting at a and ending
at b .

In [ ]: xs = np.linspace(0, 2*np.pi, 30)


ys = [np.sin(x) for x in xs] # or you could use broadcasting
plt.plot(xs, ys)
Plot options 1
In [ ]: plt.plot([1,2,3],[3,1,3], 'ro') # red circles, no lines
plt.title("this is the title")
plt.ylabel("y label")
plt.xlabel("x label")
Plot options 2
In [ ]: xs = np.linspace(-4,4, 30)
ys = [np.arctan(x) for x in xs]
plt.ylim([-4, 4]) # set the limits on the y-axis
plt.plot(xs, ys)

You might also like