| Hosted by CoCalc | Download
%md # Math 480: Open Source Mathematical Software ### 2016-04-08 ### William Stein ## **Lectures 6: Dicts and Classes (Python 3/3)** - My morning sucked: massive SageMathCloud problems. You can turn in your homework on Monday at 6pm rather than Friday at 6pm. - Screencast

Math 480: Open Source Mathematical Software

2016-04-08

William Stein

Lectures 6: Dicts and Classes (Python 3/3)

  • My morning sucked: massive SageMathCloud problems. You can turn in your homework on Monday at 6pm rather than Friday at 6pm.

  • Screencast

Another important data structure: the Python dictionary

A Python dictionary is the Python version of what computer scientists might call an "associative array".

It's what us mathematicians call a "function" (from one finite set to another). Except, like a list, it can be modified (to make another function).

d = {5:25, 10:100, 3:8}
d
{10: 100, 3: 8, 5: 25}
d[5]
25
d[10]
100
d[3]
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 904, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> NameError: name 'd' is not defined
d[7] # should fail -- since we didn't say what 7 maps to.

The keys (inputs) of a Python dictionary can be any object x in Python where hash(x) doesn't give an error.

In practice, hash(x) is supposeed to work if and only if x is immutable, i.e., really can't change.

hash(7)
7
w = [2,3] hash(w) # better not work!
Error in lines 2-2 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'

Tuples -- I mentioned them very quickly last time.

Tuples are sort of like lists, but you can change the objects they point to or the number of things they point to.

Hence... they have a chance to be immutable:

w = (2,3) hash(w) # a tuple where each thing in the tuple is immutable
3713082714463740756
d = {(2,3):5, (7,19): 26} # you can use anything immutable as the inputs (or keys or domain) d[(7,19)]
26

Not all tuples are immutable. For example:

w = ([2,3], 5) # a tuple where first thing is NOT immutable hash(w)
Error in lines 2-2 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 904, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'
w[0].append("Sage") w
([2, 3, 'Sage'], 5)

Exercise: Which of the following are immutable, i.e., hash-able, so they can be used as keys for a dictionary?

  • the string "Foo"

  • the empty list []

  • the number 3.14

  • the dictionary {7:10, 3:8}

  • the tuple ('foo', 'bar')

Make a dictionary that has all the immutable objects above as keys... and anything you want (hashable or not) as values.

{"Foo": hash("Foo"), 3.14: hash(3.14), ("foo","bar"): hash(("foo","bar"))} # Lalith
{'Foo': -5036909580522842981, ('foo', 'bar'): -998648364678804268, 3.14000000000000: 3146129223}
dic = {"Foo":[1],3.15:[2],('foo','bar'):{7:10,3:8}} #Joshua Mehlhaff
#Simon Luu hash("Foo") - immutable hash(3.14) - immutable hash(("foo", "bar")) - immutable diction = {"Foo":1, 3.14:2, ("foo", "bar"):3} diction
#Xiling dic = {'Foo':2, 3.14: 'a',('foo', 'bar'): {1:3} }
hash('Foo'),hash(3.14),hash(('foo','bar'))
d = {"Foo": 1, 3.14:2, ('foo','bar'):3} #Caitlyn Hughes
{"blah": hash("blah"), 3.14: hash(3.14), "Foo": hash("Foo"), ("foo", "bar"): hash(("foo", "bar"))} #Timothy Luong

Here's a dictionary with a function as a value:

def length(self): return sqrt(self['x']^2 + self['y']^2) self = {'x':10, 'y':15, 'length':length} self
{'y': 15, 'x': 10, 'length': <function length at 0x7f8740436ed8>}
self['length'](self)
5*sqrt(13)

Using dicts with data and functions you could model objects and work with them.

But the notation is very awkward!

Python classes do much the same thing, with vastly nicer notation!

Python Classes

Python classes let you easily create custom Python objects. They are a fantastic way of organizing math-related code.

Example:

class Vector: def __init__(self, x, y): self.x = x self.y = y def length(self): return sqrt(self.x^2 + self.y^2) def __add__(self, right): return Vector(self.x+right.x, self.y + right.y) def __repr__(self): return "The Vector (%s, %s)"%(self.x, self.y)
v = Vector(10, 15) print v
The Vector (10, 15)
v.length()
5*sqrt(13)
v + v
The Vector (20, 30)
v.__dict__
{'y': 15, 'x': 10}

Exercise:

Copy the above code and make a class Vector3 that models a vector in 3-dimensional space.

If you have time, also include a __sub__ method, to subtract one vector from another, and test that v - w works.

#Joshua Mehlhaff class Vector: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2+ self.z^2) def __add__(self, right): return Vector(self.x + right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): return Vector(self.x - right.x, self.y - right.y, self.z - right.z) def dot(self, right): return self.x*right.x + self.y*right.y + self.z*right.z def cross(self, right): return Vector(self.y*right.z-self.z*right.y, self.z*right.x-self.x*self.z, self.x*right.y-self.y*right.x) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z)
# Doudou Feng class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, right): return Vector3(self.x + right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The representation of the vector is (%s, %s, %s)"%(self.x, self.y, self.z) def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z)
class Vector3: #Ankit Kumar def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z) def cross_prod(self, other): return Vector3(self.y * other.z - self.z * other.y, other.x * self.z - other.z * self.x, self.x * other.y - self.y * other.x) def __repr__(self): return "Ankit's Vector3 (%s, %s, %s)"%(self.x, self.y, self.z)
# Mari Chinn class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, right): return Vector3(self.x + right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The representation of the vector is (%s, %s, %s)"%(self.x, self.y, self.z) def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z)
#Alta Steward class Vector3: def __init__(self, x, y,z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): return Vector3(self.x-right.x, self.y-right.y, self.z-right.z) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z)
# Vinh X Mao class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x + right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "Vinh's Vector3 (%s, %s, %s)"%(self.x, self.y, self.z) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z) def __cross__(self, right): return Vector3(self.y * right.z - aelf.z * right.y, self.x * right.z - self.z * right.x, self.x * right.y - self.y * right.x)
#Simon Luu class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z) def __cross__(self, right): return Vector3(self.y * right.z - self.z * right.y, self.x * right.z - self.z * right.x, self.x * right.y - self.y * right.x) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z)
#Mac Hollister class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x + right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z) def __sub__(self, other): return Vector3(self.x-other.x, self.y-other.y, self.z-other.z) def cross(self, other): return Vector3(self.y * other.z - self.z * other.y, self.x * other.z - self.z * other.x, self.x * other.y - self.y * other.x)
class Vector:#John Menefee def __init__(self, x, y, z): self.x = x self.y = y self.z = z print "I just initialized myself" def length(self): #length of vector return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right):#adds a vector return Vector(self.x + right.x, self.y + right.y, self.z + right.z) def __sub__(self, right):#subtracts a vector return Vector(self.x - right.x, self.y - right.y, self.z - right.z) def __crossprod__(self, right):#cross product return Vector(self.x * right.x, self.y * right.y, self.z * right. z) def __repr__(self):# string representation return "John's Vector (%s, %s, %s)"%(self.x, self.y, self.z)
#Caitlyn Hughes class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return (self.x^2 + self.y^2 + self.z^2)^(1/2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The 3D Vector is (%s, %s, %s)"%(self.x, self.y, self.z) def __sub__(self,right): return Vector3(self.x-right.x, self.y - right.y, self.z - right.z) def __crossproduct__(self,right): return Vector3(self.y*right.z - self.z*right.y, self.z*right.x - self.x*right.z, self.x*right.y - self.y*right.x)
class Vector3: #Timothy Luong def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z)
8eb8a90-9b92-4c2c-bfb4-4ee8df3c7eff︠
#Boyu Deng class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __repr__(self): return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z) def __sub__(self): return Vector3(self.x-right.x, self.y-right.y, self.z-right.z)
class Vector3: # Lalith def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): # length of vector return sqrt(self.x**2 + self.y**2 + self.z**2) def __add__(self, right): # adds a vector return Vector3(self.x + right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): # subtracts a vector return Vector3(self.x - right.x, self.y - right.y, self.z - right.z) def cross(self, right): # computes cross product return Vector3(self.y * right.z - self.z * right.y, right.x * self.z - right.z * self.x, self.x * right.y - self.y * right.x) def __eq__(self, other): return self.x == other.x and self.y == other.y and self.z == other.z def __repr__(self): # string representation return "The Vector (%s, %s, %s)"%(self.x, self.y, self.z) # Quan Nguyen class Vector3: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def length(self): return sqrt(self.x^2 + self.y^2 + self.z^2) def __add__(self, right): return Vector3(self.x+right.x, self.y + right.y, self.z + right.z) def __sub__(self, right): return Vector3(self.x - right.x, self.y - right.y, self.z - right.z) def __repr__(self): return "My Vector3 (%s, %s, %s)"%(self.x, self.y, self.z) q = Vector3(1,5,99)
q+q