Review

  • Last week I talked about lists.
  • Lists are like arrays in other languages.
    • They are quick to access but may be slow to extend.
  • Literal lists are represented with brackets [ and ]

Here are examples of list literals:

[1, 2, 3, 4]                  # A list of ints
["hello", "list", "world"]    # A list of strings 
[1, 'hello', 2, 'list', True] # A mixed type list 
[[1, 'Hello'], [2, 'World]]   # A list of lists
  • Lists are held in variables just like ordinary types.
  • Some common math operations are defined on lists.

You can add lists together with the plus + operator:

>>> foo = [1, 2, 3, 4]
>>> bar = ["hello", "list", "world"]
>>> foo + bar 
[1, 2, 3, 4, 'hello', 'list', 'world']

You can multiply lists (causing them to repeat) with the times * operator:

>>> foo * 3 
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
  • List elements are accessed using brackets [ and ]
  • List indexes start a 0
>>> foo[0]
1
>>> foo[2]
3
>>> foo[-1]
4

Simply looping over a list:

>>> for item in foo : 
...   print (item) 
... 
1
2
3
4

Looping over a list with indexes and items using the enumerate() function:

>>> for index, item in enumerate(foo) : 
...   print (index, item) 
... 
0 1
1 2
2 3
3 4

Looping over an arbitrary range of integers using a range:

>>> for i in range(0,5) : 
...   print (i) 
... 
0
1
2
3
4
  • We looked at while loops.
  • Use a while loop when you don't know how many times the loop should run.
>>> while True : 
...   num = int(input('Enter a number from 1 to 10: '))
...   if num >= 1 and num <= 10 : 
...     break 
... 
Enter a number from 1 to 10: -1
Enter a number from 1 to 10: 0
Enter a number from 1 to 10: 5

Dictionaries

  • Dictionaries are like lists, but instead of an index you can use any value.
  • The index of a dictionary is known as a key
    • Each key holds a value
  • Dictionary literals are declared with curly braces
    • The key is on the left side of the colon
    • The value is on the right side of the colon

Here's a dictionary literal:

{} # An empty dictionary
{'key1': 'value1', 'key2': 'value2', 3 : 3 }

You can assign literals to a variable like this:

foo = {'key1': 'value1', 'key2': 'value2', 3 : 3 }
  • Dictionaries are accessed similarly to lists.
  • Watch out! Make sure you put quotes around strings.
>>> foo['key1']
'value1'
>>> foo['key2']
'value2'
>>> foo[3]
3
  • You can assign new keys to a dictionary using the index operator
  • You can change existing keys too
    • A dictionary can only have one value per key
    • Reassigning a key replaces the old value with the new value.
>>> foo['newval'] = 'blah'
>>> foo 
{'key1': 'value1', 'key2': 'value2', 3: 3, 'newval': 'blah'}
>>> foo['newval'] = 10 
>>> foo 
{'key1': 'value1', 'key2': 'value2', 3: 3, 'newval': 10}
  • You can loop over dictionaries easily with a for loop

This simple loop iterates over keys:

>>> for key in foo : 
...   print (key) 
... 
key1
key2
3
newval

You can loop over values too:

>>> for value in foo.values() : 
...   print (value) 
... 
value1
value2
3
10

You can also loop over both keys and values:

>>> for key, value in foo.items() : 
...   print (key, value) 
... 
key1 value1
key2 value2
3 3
newval 10

Dictionary Operations

  • It's often useful to test if a dictionary contains a key.
  • The in operator does that.

Test if an environment variable is set:

>>> import os 
>>> if 'USER' in os.environ : 
...   print (f"$USER is set to {os.environ['USER']}")
... 
$USER is set to maximus
  • You can ask the opposite question with not in

Check if a key is not in a dictionary:

>>> foo = {'one' : 1, 'two': 2}
>>> if 'three' not in foo : 
...   print ('Better add three') 
... 
Better add three
  • The in operator works on lists too!
    • It tests if a value exists in the list.
  • The get() function works like the brackets except for what happens when the key doesn't exist.
    • get() returns None
    • The index operator raises a KeyError

Here's an example of how get() and index operator differ:

>>> foo.get('badkey') 
>>> foo['badkey'] 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'badkey'
  • The clear() function removes all key/values from the dictionary
  • The len() function works on dictionaries (just like lists)

Here's an example of len() with dictionaries.

>>> foo = {'one' : 1, 'two': 2}
>>> len(foo)
2
  • Notice that the length is the number of key/value pairs.
  • You can merge dictionaries using the update() function
>>> foo = {'one' : 1, 'two': 2}
>>> bar = {'three': 3, 'four': 4}
>>> foo.update(bar)
>>> foo 
{'one': 1, 'two': 2, 'three': 3, 'four': 4}

Be careful! You can overwrite keys this way.

>>> foo.update({'one': 100}) 
>>> foo
{'one': 100, 'two': 2, 'three': 3, 'four': 4}

Dictionary Data Structures

  • Python allows you to mix and match lists and dictionaries
  • You can make interesting data structures this way
  • Consider making a phone book
    • Each entry has the some data about a person.
      • Email Address
      • Mobile Number
      • Home Number
      • Work Number
  • You can represent each entry as a dictionary.
>>> contacts = {}
>>> contacts['Bob Smith'] = { 'email' : 'bob@company.com', 
...   'mobile' : '555-1212', 
...   'home' : '555-3434', 
...   'work' : '555-6767'
... }
  • Now we can access Bob's information
>>> contacts['Bob Smith']['email'] 
'bob@company.com'
  • You could also make a dictionary with users of your blog website
  • Users have the standard attributes:
    • Real Name
    • Email Address
    • Posts
  • A post contains some attributes:
    • Title
    • Text

Now let's create a user and some posts:

>>> post1 = {'title': 'First post!',  
...   'text': "This is my first post to my new blog."
... }
>>> post2 = {'title': 'Ate Cereal for Breakfast.', 
...   'text': "I ate cereal today they were Heritage O's. High in fiber."
... }
>>> bloggers = {
...   'mike' : {
...     'name' : 'Mike Matera', 
...     'email' : 'matera@matera.com',
...     'posts' : [post1, post2]
...   }
... }

Now you can access a post like this:

>>> bloggers['mike']['posts'][0]['title']
'First post!'
>>> bloggers['mike']['posts'][0]['text']
'This is my first post to my new blog.'
  • When you have complex data structures it helps to have functions to perform common activities.
  • Functions help you by naming common operations.
  • Functions help keep your structure consistent.
  • Let's add functions to manipulate our data.

Here's a function that creates a user.

def create_user(data, username, realname, email) : 
    ''' Create a user in a blog data structure 
 
    Args: 
        data - The data structure to use 
        username - The user's username 
        realname - The uers's real name 
        email - The users's email address. 
    '''
    data[username] = {}
    data[username]['name'] = realname 
    data[username]['email'] = email 
    data[username]['posts'] = []
  • Important: That when the user is created they get an empty list of posts.
  • I pass the data structure in to avoid using global data

Here's a function that adds a post:

def add_post(data, username, title, text) : 
    ''' Append the post to the user's list of blog posts. 
 
    Args:
        data - The blog data structure to use. 
        username - The user who wrote the post. 
        title - The title of the new post. 
        text - The text of the post. 
    '''
    data[username]['posts'].append({'title' : title, 'text' : text})    
  • The previous functions change our data.
  • It's very useful to have functions that access data.

Here's a function that prints all the posts from a particular user:

def print_blogs(data, username) : 
    ''' Print all of the blog entries for a user.
 
    Args:
        data - The blog data structure to use. 
        username - The user to print. 
    '''
    for blog in data[username]['posts'] : 
        print ('Title:', blog['title'])
        print ('Text:', blog['text'])

Data Structure Representations

  • When your blog entries are in a variable they're in the computer's memory
  • If your program exits your data is lost.
  • It's important to be able to save your program data
    • To do that you must pick a representation.
  • Javascript Object Notation (JSON) is a popular data format.
  • JSON is well supported by Python
  • You can save most Python data using JSON easily

Here's how to use JSON in a program:

>>> import json 
>>> json.dumps(bloggers) 
'{"mike": {"name": "Mike Matera", "email": "matera@matera.com", "posts": [{"title": "First post!", "text": "This is my first post to my new blog."}, {"title": "Ate Cereal for Breakfast.", "text": "I ate cereal today they were Heritage O\'s. High in fiber."}]}}'
  • JSON data is very similar to how data is represented using Python literals
  • The dumps() function converts Python data into a JSON string
  • The loads() function does the opposite.
>>> json_string = json.dumps(bloggers) 
>>> data = json.loads(json_string)
>>> data 
{'mike': {'name': 'Mike Matera', 'email': 'matera@matera.com', 'posts': [{'title': 'First post!', 'text': 'This is my first post to my new blog.'}, {'title': 'Ate Cereal for Breakfast.', 'text': "I ate cereal today they were Heritage O's. High in fiber."}]}}
  • We can add functions to our blogging program that allow users to load and store the blog database.

Here's a function that loads the blog database:

def load_blogs(filename) : 
    with open(filename) as f : 
        return json.loads(f.read())

And a corresponding function that saves blogs:

def save_blogs(data, filename) :
    with open(filename, 'w') as f : 
        f.write(json.dumps(data))

Advanced: Your First App Engine Flask Project

Lecture Files

Files from this lecture can be downloaded from here: