Python Algorithm
Python Algorithm
Agenda
- language overview
- built-in types, operators and constructs
- functions, classes, and modules
- stdlib: I/O, testing, timing
Computer
Science Science
Not exhaustive!
- this is not a language course
- Python is a means to an end
(writing data structures & algorithms)
- you are responsible for mastering the
language!
Computer
Science Science
IDE recommendation
- We will not be using an official IDE
- Text editor (vim/emacs) + command
line interpreter will suffice
- If you want/need one, I recommend
PyCharm (from jetbrains.com)
Computer
Science Science
§Overview
Computer
Science Science
Python is …
interpreted,
dynamically-typed,
automatically memory-managed,
and supports procedural, object-oriented,
imperative and functional paradigms
Computer
Science Science
§Types, Operators
and Constructs
(that matter to us)
Computer
Science Science
Boolean operators
Comparison operators
Computer
Science Science
Numeric operators
Computer
Science Science
https://docs.python.org/3/library/functions.html
Computer
Science Science
Compound types
>>> 'hello'
'hello'
>>> 'hello' + ' ' + 'world'
'hello world'
>>> 'lo wo' in ('hello' + ' ' + 'world')
True
>>> 'world' * 3
'worldworldworld'
>>> len('hello')
5
>>> 'hello world'[3:10]
'lo worl’
>>> 'hello'[2:4] = 'ww'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Computer
Science Science
puzzle = """4.....8.5
.3.......
...7..... (newlines (‘\n'))
...
.2.....6.
(whitespace) ....8.4..
....1....
...6.3.7.
5..2.....
1.4......"""
Computer
Science Science
.3.......
...7.....
.2.....6.
....8.4..
....1....
...6.3.7.
5..2.....
1.4......"""
[ '4.....8.5',
'.3.......',
'...7.....',
'.2.....6.',
'....8.4..',
'....1....',
'...6.3.7.',
'5..2.....',
‘1.4......' ]
Computer
Science Science
Hewwo-uh-wabbit
Computer
Science Science
for r in puzzle_rows:
print(r, '->', r.count('.'), 'blanks')
blank_counts = []
for r in puzzle_rows:
blank_counts.append(r.count('.'))
[6, 8, 8, 7, 7, 8, 6, 7, 7]
[6, 8, 8, 7, 7, 8, 6, 7, 7]
Computer
Science Science
rows = 'ABCDEFGHI'
cols = '123456789'
squares = []
for r in rows:
for c in cols:
squares.append(r + c)
print(len(squares))
print(squares[0:len(squares):5])
81
[ 'A1', 'A6', 'B2', 'B7', 'C3', 'C8', 'D4', 'D9',
'E5', 'F1', 'F6', 'G2', 'G7', 'H3', 'H8', 'I4', 'I9']
Computer
Science Science
rows = 'ABCDEFGHI'
cols = '123456789'
print(len(squares))
print(squares[0:len(squares):5])
81
[ 'A1', 'A6', 'B2', 'B7', 'C3', 'C8', 'D4', 'D9',
'E5', 'F1', 'F6', 'G2', 'G7', 'H3', 'H8', 'I4', 'I9']
Computer
Science Science
identifying “units”
rows = 'ABCDEFGHI'
cols = '123456789'
rows = 'ABCDEFGHI'
cols = '123456789'
all_units = # ?
print(len(all_units))
print(all_units)
27
[['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
...
['I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'],
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
...
['A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'],
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'],
...
['G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9']]
Computer
Science Science
hints:
- result is the concatenation of multiple list
comprehension expressions
- each list comprehension must create
a list of lists (each unit is a list)
- try to do it in pieces first!
Computer
Science Science
Computer
Science Science
c2_units = # ?
Computer
Science Science
print(square_units[0])
('A1',
[['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']])
Computer
Science Science
to_find = 'C2'
for entry in square_units:
if entry[0] == to_find:
units = entry[1]
break
else: # enter when loop exhausts all values (i.e., no break)
units = None # special value that represents ... nothing
print(units)
Operation Result
Dictionary operations
Computer
Science Science
try:
dd_ego = alter_egos['Dr. Doom']
except:
print("Dr. Doom's alter ego not known")
else:
print('Dr. Doom =', dd_ego)
finally:
print('Thanks for playing!')
print(alter_egos.get('Superman', 'unknown'))
print(alter_egos.get('Dr. Doom', 'unknown'))
Clark Kent
unknown
Computer
Science Science
print(alter_egos.get('Superman'))
print(alter_egos.get('Dr. Doom'))
Clark Kent
None
Computer
Science Science
for k, v in alter_egos.items():
print(k, '=>', v)
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
alpha_num = {}
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
alpha_num = {alpha[i]: i+1 for i in range(0, len(alpha))}
back to Sudoku:
all_units = ([[r+c for c in cols] for r in rows] +
[[r+c for r in rows] for c in cols] +
[[r+c for r in rs for c in cs]
for rs in ('ABC', 'DEF', 'GHI')
for cs in ('123', '456', '789')])
c2_units = units['C2']
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(c2_peers)
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Computer
Science Science
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Problems:
1. List contains duplicate peers
2. List of peers of a square should not
include the square itself ! (C2, above)
Computer
Science Science
Operation Result
x in s tests if x is in set k
s1 ^ s2 returns a new set with elements from either s1 or s2 but not both
Set operations
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(c2_peers)
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(sorted(c2_peers)) # sorting into list for inspection
20
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C3', 'C4',
'C5', 'C6', 'C7', 'C8', 'C9', 'D2', 'E2', 'F2', 'G2',
'H2', 'I2']
Computer
Science Science
c2_peers = peers['C2']
print(len(c2_peers))
print(sorted(c2_peers))
20
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C3', 'C4',
'C5', 'C6', 'C7', 'C8', 'C9', 'D2', 'E2', 'F2', 'G2',
'H2', 'I2']
Computer
rows = 'ABCDEFGHI' Science Science
cols = '123456789'
def any(iterable):
for element in iterable:
if element:
return True
return False
Computer
Science Science
§Functions
Computer
Science Science
def foo():
pass # special statement -- does nothing!
# (useful as a placeholder)
def bar():
"""Calls foo. This is a function *docstring*.
It should briefly describe what the function
does. I won't always use them in slides, but
you should!"""
foo() # call foo
Computer
Science Science
print(mysum(1, 2))
print(mysum('hello', 'world'))
3
helloworld
Computer
Science Science
def mysum_v2(vals):
"""This version takes a list of vals to add"""
accum = 0 # ← restricts to numbers
for item in vals:
accum += item
return accum
print(mysum_v2([1, 2, 3, 4, 5]))
print(mysum_v2(range(10)))
print(mysum_v2(['hello', 'world']))
15
45
Traceback (most recent call last):
File "functions.py", line 12, in <module>
print(mysum_v2(['hello', 'world']))
File "functions.py", line 7, in mysum_v2
accum += item
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
Computer
Science Science
15
helloworld
(1, 2, 5)
Computer
Science Science
print(mysum_v4([1, 2, 3, 4, 5]))
print(mysum_v4(['hello', 'world'], ''))
print(mysum_v4(['hello', 'world'], start=''))
print(mysum_v4(start='-->', vals=['a', 'b', 'c']))
15
helloworld
helloworld
-->abc
Computer
Science Science
print(mysum_v5(1, 2, 3, 4))
print(mysum_v5('hello', ' ', 'world', start='>'))
10
>hello world
Computer
Science Science
550
Computer
Science Science
print(reduce(add, 1, 2, 3, 4))
print(reduce(add, 'hello', 'world', start=''))
10
helloworld
Computer
Science Science
print(reduce(mult, 1, 2, 3, 4))
print(reduce(mult, 1, 2, 3, 4, start=1))
0
24
Computer
Science Science
add(5, 6) # => 11
mult(5, 6) # => 30
pow_of_2(10) #=> 1024
24
30
19
{8, 9}
Computer
Science Science
is
fun
cakes
ingesting
Computer
Science Science
Got 1 2 3
Got 1 2 3
Got 1 2 3
Computer
Science Science
>>> a = 10
>>> b = a + 10
>>> tmp = a
>>> a = b
>>> b = tmp
>>> (a, b)
(20, 10)
>>> l = [10, 9, 8, 7, 6, '...']
>>> l[-1] = 5
>>> l[len(l):] = [4, 3, 2, 1, 'Bang!']
>>> l
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 'Bang!']
Computer
Science Science
def fibonacci(nth):
a, b = 1, 1
for _ in range(nth-1):
a, b = b, a+b
return a
puzzle = """4.....8.5
.3.......
{'A1': '4',
...7.....
'A2': None,
.2.....6. 'A3': None,
....8.4.. 'A4': None,
....1.... 'A5': None,
...6.3.7. 'A6': None,
5..2..... 'A7': '8',
1.4......""" 'A8': None,
'A9': '5',
...
'I1': '1',
def parse_puzzle(puz): 'I2': None,
puzzle = [c if c.isdigit() else None 'I3': '4',
for c in puz if c not in ' \n'] 'I4': None,
assert(len(puzzle) == 81) 'I5': None,
return {squares[i]: puzzle[i] 'I6': None,
'I7': None,
for i in range(0, len(squares))}
'I8': None,
'I9': None}
print(parse_puzzle(puzzle))
Computer
Science Science
Demo
Computer
Science Science
def search(sol):
# find a square with the least number of values > 1
#
# (1) "guess" one of the values (assign it) and
# try to solve the rest of the puzzle
#
# (2) if we guessed wrong and the solution is broken,
# backtrack --- i.e., restore the original values
# and guess another value
Computer
Science Science
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
# (1) "guess" one of the values (assign it) and
# try to solve the rest of the puzzle
#
# (2) if we guessed wrong and the solution is broken,
# backtrack --- i.e., restore the original values
# and guess another value
Computer
Science Science
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
assign(sol, sq, val)
search(sol)
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
def search(sol):
if any(not sol[s] for s in squares):
# a square with no values is illegal
return False
elif all(len(sol[s]) == 1 for s in squares):
# if all squares have just one value, we're done
return True
else:
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
orig = sol.copy()
for val in orig[sq]:
assign(sol, sq, val)
if not search(sol):
sol.update(orig)
else:
break
Computer
Science Science
def search(sol):
if any(not sol[s] for s in squares):
return False
elif all(len(sol[s]) == 1 for s in squares):
return True
else:
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
orig = sol.copy()
for val in orig[sq]:
assign(sol, sq, val)
if search(sol):
return True # propagate success back up
else:
sol.update(orig)
else:
return False # no guesses worked = earlier fail
Computer
Science Science
Demo
Computer
Science Science
class Point:
pass
p = Point()
p.x = 10
p.y = 20
print('x=', p.x, 'y=', p.y)
x= 10 y= 20
Computer
Science Science
class Point:
def __init__(self): # `self` refers to "this" object
self.x = 10
self.y = 20
p = Point()
print('x=', p.x, 'y=', p.y)
x= 10 y= 20
Computer
Science Science
class Point:
def __init__(self, xinit, yinit):
self.x = xinit
self.y = yinit
p = Point(15, 25)
print('x=', p.x, 'y=', p.y)
x= 15 y= 25
Computer
Science Science
class Point:
...
def translate(self, dx, dy):
self.x += dx
self.y += dy
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
p = Point(0, 0)
p.translate(3, 4)
print('dist of', p, '=', p.dist_to_origin())
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
p = Point(0, 0)
Point.translate(p, 4, 3) # same as p.translate(4, 3)
print('dist of', p, '=', Point.dist_to_origin(p))
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
q = Point(0, 0)
r = Point(0, 0)
print(q == r) # based on object identity (reference)
False
Computer
Science Science
class Point:
...
def __eq__(self, other): # called for '=='
if isinstance(other, Point):
return self.x == other.x and self.y == other.y
return NotImplemented
p = Point(10, 20)
q = Point(10, 20)
r = Point(30, 40)
print(p == q)
print(p == r)
print(p == 'hello')
True
False
False
Computer
Science Science
class Point:
...
def __add__(self, other): # called for '+'
if isinstance(other, Point):
return Point(self.x+other.x, self.y+other.y)
return NotImplemented
p = Point(10, 20)
q = Point(10, 20)
r = Point(30, 40)
print(p + q + r)
print(p + 10)
(50,80)
Traceback (most recent call last):
File "classes.py", line 95, in <module>
print(p+10)
TypeError: unsupported operand type(s) for +: 'Point' and 'int'
Computer
Science Science
class Point:
...
def __iter__(self):
yield self.x # ok to not understand this now!
yield self.y # ditto this
p = Point(19, 20)
for coord in p:
print(coord)
l = list(p)
print(l)
cs = [c for c in p]
print(cs)
19
20
[19, 20]
[19, 20]
Computer
Science Science
class Point:
prev_coords = [] # class variable!
p = Point()
q = Point(1, 2)
p = Point()
q = Point(1, 2)
def dist_to_origin(self):
dist2d = super().dist_to_origin()
return sqrt(dist2d ** 2 + self.z ** 2)
p = Point3D(1, 1, 1)
print('dist of', p, '=', p.dist_to_origin())