CSC207 Software Design
Lectures
Python Dictionaries, Functions, and Modules

Dictionaries

Another name for maps

Also called hashes and associative arrays

Built in to the language

Very handy to be able to just write them down

Creating and Indexing

Create by putting key/value pairs inside {}

{"Newton":1642, "Darwin":1809}

Empty dictionary written {}

Index a dictionary using []

birthday = {"Newton":1642, "Darwin":1809}
print birthday["Darwin"], birthday["Newton"]
1809 1642

Can only access keys that are present

birthday = {"Newton":1642, "Darwin":1809}
print birthday["Turing"]
KeyError: Turing

Test for presence of key using k in d

birthday = {"Newton":1642, "Darwin":1809}
if "Turing" in birthday:
    print birthday["Turing"]
else:
    print "Who?"
Who?

Iterating

for k in d iterates over keys, not values

Inconsistent but useful

birthday = {"Newton" : 1642,
            "Darwin" : 1809,
            "Turing" : 1912}
for name in birthday:
  print name, birthday[name]
Turing 1912
Newton 1642
Darwin 1809

Adding Information

Assigning to a dictionary key:

Creates a new entry if key not in dictionary

Overwrites value if key already in dictionary

birthday = {}
birthday["Darwin"] = 1809
birthday["Newton"] = 1942  # oops
birthday["Newton"] = 1642
print birthday
{"Darwin": 1809, "Newton": 1642}

Counting Frequency

val = ['Be','Mg','Mg','Ca','Be','Mg']
freq = {}
for v in val:
    if v in freq:
        freq[v] += 1
    else:
        freq[v] = 1
print freq
{'Be' : 2, 'Mg' : 3, 'Ca' : 1}

Common Dictionary Methods

d.clear() Empty the dictionary.
Use del d[k] to delete specific items.
d.get(k, default) Get value associated with k,
or default if k not present.
d.has_key(k) Test whether k is in d.
d.keys() Get list of d's keys.
d1.update(d2) Merge keys and values from d2 into d1.
d.values() Get list of d's values.

A Better Way to Count

val = ['Be','Mg','Mg','Ca','Be','Mg']
freq = {}
for v in val:
    freq[v] = freq.get(v, 0) + 1
print freq
{'Be' : 2, 'Mg' : 3, 'Ca' : 1}

Printing in Sorted Order

...build up freq as before...
keys = freq.keys()
keys.sort()
for k in keys:
    print k, freq[k]
Be 2
Ca 1
Mg 3

Inverting a Dictionary

seq = "GATTAATGCCATTGCTTA"
freq = {}
for c in seq:
    freq[c] = freq.get(c, 0) + 1
count = {}
for (k, v) in freq.items():
    count[v] = count.get(v, '') + k
print count
{3: 'CG', 5: 'A', 7: 'T'}

Counting Word Frequency

import sys
freq = {}
for line in sys.stdin:
    words = line.split()
    for w in words:
        freq[w] = freq.get(w, 0) + 1
keys = freq.keys()
keys.sort()
for k in keys:
    print k, freq[k]

A Simple Function

# define function
def ave(x, y):
    return (x + y) / 2.0

# use function
print ave(20, 30)
25.0

The Rules

Define a new function using def

Really creating a function object, then assigning it to a variable

Argument names follow in parentheses

No types

Finish at any time with return

Functions without return statements return None

Scope

Variables created in function are local to it

x = 123
def f(arg):
    x = arg
    print "x in f is", x
f(999)
print x
x in f is 999
123

Memory

Function arguments always copied

Which means structures are aliased

Just as in Java

def mutate(x, y):
    x = 0
    y[0] = 0
a = 1
b = [1, 1, 1]
mutate(a, b)
print a, b
1, [0, 1, 1]

Default Argument Values

Can provide defaults for arguments

Arguments without defaults must come first

def withTax(val, percent=15):
    return val * (1.0 + percent/100.0)
print withTax(10.00)       # default
print withTax(10.00, 7)    # explicit
11.5
10.7

Named Arguments

Can pass arguments in any order using names

def show(first, second):
    print first, second
show(1, 2)
show(second=9, first=0)
1 2
0 9

Mixing Defaults and Names

Matching rules are intuitive

Match left-to-right

Unnamed must precede named

def show(first, second, third=3):
    print first, second, third
show(second=9, first=0)
show(1, 2, 5)
0 9 3
1 2 5

Extra Arguments

Any extra unnamed arguments put in a tuple called *extra

A tuple is like a constant list

Uses () instead of []

Exercise for the reader: look up tuples in Python documentation

Only the * matters: could call the argument *fred

If no * argument present, extra values are illegal

def show(first, *extra):
    print first, extra
show(10, 20, 30, 40)
10 (20, 30, 40)

Extra Named Arguments

Any extra named arguments put in a dictionary called **named

Again, only the ** is important

def user(id, **named):
    print id, "=", named
user(0, name="Greg", age=40)
user(1, hair="some", eyes=2)
0 = {'age' : 40, 'name' : 'Greg'}
1 = {'hair' : 'some', 'eyes' : 2}

Extra Argument Example

def ex(a, b, c=3, d=4, *extra, **named)
Call a b c d extra named
ex(1, 2) 1 2 3 4 () {}
ex(1, 2, 8) 1 2 8 4 () {}
ex(1, 2, d=8) 1 2 3 8 () {}
ex(1, 3, 5, 7, 9) 1 3 5 7 (9,) {}
ex(1, 2, j=6) 1 2 3 4 () {'j':6}

Creating Modules

Any Python file can be loaded as a module using import module

File called xyz.py becomes module xyz

Statements executed as program loads

Libraries typically just define constants and functions

Module contents referred to as module.content

E.g. sys.argv

Can also use

from module import name1, name2

from module import *

# stuff.py
value = 123
def printVersion():
    print "Stuff Version 2.2"
# loader.py
import stuff
print stuff.value     # note: modulename dot thing
stuff.printVersion()  # note again
$ python stuff.py
$ python loader.py
123
Stuff Version 2.2

Telling Them Apart

Special variable __name__ is module's name

Set to "__main__" when the file is run from the command line

Set to the module's name when it is loaded by something else

Often used to include self-tests in module

Tests use assert when module run directly

Self-Test Example

def double(val):
    return val * 2

if __name__ == '__main__':
    print "testing double"
    assert double(0) == 0
    assert double('a') == 'aa'
    assert double([1]) == [1, 1]
    print "tests passed"

$Id: pydfm.html,v 1.1.1.1 2004/01/04 05:02:31 reid Exp $