Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 16658

Math 152: Intro to Mathematical Software

2017-01-20

Kiran Kedlaya; University of California, San Diego

adapted from lectures by William Stein, University of Washington

**Lecture 5: Dicts and Classes **

Guest lecturer: William Stein (Professor, University of Washington; CEO, SageMath Inc.)

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 ( not to be confused with a Python "function", which is really a subroutine).

def foo(n): ## A Python function, not a mathematical function return random()
foo(5)
0.3704000361759935
foo(5)
0.8220957522968851
d = {5:25, 10:100, 3:8, 3:'another value'}
d
{10: 100, 3: 'another value', 5: 25}
d[10] # You can change existing values...
100
d[5]
25
d[10] = 'foo bar'
d[10]
'foo bar'
d[9] = 0 # Or create new ones... print(d)
{9: 0, 10: 'foo bar', 3: 'another value', 5: 25}
d
{9: 0, 10: 'foo bar', 3: 'another value', 5: 25}
for a in d.keys(): print id(a)
139756685828336 139756685828240 139756685828480 139756685828576
d[5]
25
d[10]
'foo bar'
d[3]
'another value'
d[7] # should fail -- since we didn't say what 7 maps to.
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> KeyError: 7
d['william stein']
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> KeyError: 'william stein'

Aside: Python has a form of flow control for catching runtime errors.

try: d[7] except KeyError: print "there was an error"
there was an error
try: print d[10] except KeyError: print "there was an error"
foo bar

You can also use get and specify a default if there is no key in the dict

c[10]
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> NameError: name 'c' is not defined
d.
d[7]
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> KeyError: 7
d.get(7, 'default_value')
'default_value'
7 in d
False
n = 930980348028348
"error %s is not prime"%n
'error 930980348028348 is not prime'

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 supposed to work if and only if x is immutable, i.e., really can't change.

s = 'lksdjfljsdfljasdfj'
s[4]
'j'
s[4] = 'Y'
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: 'str' object does not support item assignment
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-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'

We saw tuples briefly in the previous lecture.

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

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

d = {5:'a', [2,3]:5}
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'
s = 'abc' t = ['a', 'b', 'c'] s[2] t[2]
'c' 'c'
t[2] = 'x' s[2] = 'x'
Error in lines 2-2 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: 'str' object does not support item assignment
t
['a', 'b', 'x']
list(s)
['a', 'b', 'c']
x = [2,3] d[x]
Error in lines 2-2 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'
hash([2,3])
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'
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-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'
id(w[0])
139756685803672
w[0].append("Sage") w
([2, 3, 'Sage'], 5)
id(w[0])
139756685803672
︠d69767d1-ea3c-4e8b-8960-5d3d67a048ba︠
︠d8e6caf9-1227-463b-a536-9806bd5fba3b︠

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.

hash("Foo") # no error <===> it's immutable
-5036909580522842981
d = {"Foo":(1,2), 3.14:5} # IS A DICTIONARY
type(d)
<type 'dict'>
d
{'Foo': (1, 2), 3.14000000000000: 5}
hash(d)
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'dict'

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

def length(self): return sqrt(self['x']^2 + self['y']^2) self = {'x':10, 'y':25, 'length':length} self
{'y': 25, 'x': 10, 'length': <function length at 0x7f1ba39bbe60>}
hash(length) {length:10, 'x':5}
8734792858598 {'x': 5, <function length at 0x7f1ba39bbe60>: 10}
self['length'](self)
5*sqrt(29)

Using dicts with data and functions, you could try to model mathematical 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 (as well as many other types of code).

Example:

class Vector: def __init__(self, x, y): self.x = x self.y = y print "I just initialized myself" def length(self): print "hi this is length" return sqrt(self.x^2 + self.y^2) def __add__(self, right): return Vector(self.x+right.x, self.y + right.y) # change to Vector3 def __repr__(self): return "(%s, %s)"%(self.x, self.y)
v = Vector(e, pi) v
I just initialized myself (e, pi)
type(pi)
<type 'sage.symbolic.expression.Expression'>
%time s = pi.N(digits=10^6)
CPU time: 2.16 s, Wall time: 2.20 s
v = Vector(3,4) v
I just initialized myself (3, 4)
v.length()
hi this is length 5
s = e + pi + sqrt(2) type(s)
<type 'sage.symbolic.expression.Expression'>
type(s.N(100))
<type 'sage.rings.real_mpfr.RealNumber'>
v = Vector(e, pi)
I just initialized myself
s = v.length() s
hi this is length sqrt(pi^2 + e^2)
s.N(digits=100)
4.154354402313313572948121466679053097883112964956925650570131181071504645063424705663305915070972059
v.x
e
v.y
pi
v.length()
hi this is length sqrt(pi^2 + e^2)
v + v
I just initialized myself William's vector (2*e, 2*pi)
v.__dict__
{'y': pi, 'x': e}

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.

v.cross_product(w) # add an implementation of this (it's fine if you have to look it up...)
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> AttributeError: Vector instance has no attribute 'cross_product' Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-7.3/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 976, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> AttributeError: Vector instance has no attribute 'cross_product'