# Non-Programmer's Tutorial for Python 3/Dictionaries

This chapter is about dictionaries. Dictionaries have keys and values.
The keys are used to find the values. Here is an example of a dictionary
in use:

``` python
def print_menu():
    print('1. Print Phone Numbers')
    print('2. Add a Phone Number')
    print('3. Remove a Phone Number')
    print('4. Lookup a Phone Number')
    print('5. Quit')
    print()

numbers = {}
menu_choice = 0
print_menu()
while menu_choice != 5:
    menu_choice = int(input("Type in a number (1-5): "))
    if menu_choice == 1:
        print("Telephone Numbers:")
        for x in numbers.keys():
            print("Name: ", x, "\tNumber:", numbers[x])
        print()
    elif menu_choice == 2:
        print("Add Name and Number")
        name = input("Name: ")
        phone = input("Number: ")
        numbers[name] = phone
    elif menu_choice == 3:
        print("Remove Name and Number")
        name = input("Name: ")
        if name in numbers:
            del numbers[name]
        else:
            print(name, "was not found")
    elif menu_choice == 4:
        print("Lookup Number")
        name = input("Name: ")
        if name in numbers:
            print("The number is", numbers[name])
        else:
            print(name, "was not found")
    elif menu_choice != 5:
        print_menu()
```

And here is my output:

`1. Print Phone Numbers`\
`2. Add a Phone Number`\
`3. Remove a Phone Number`\
`4. Lookup a Phone Number`\
`5. Quit`\
\
`Type in a number (1-5): `**`2`**\
`Add Name and Number`\
`Name: `**`Joe`**\
`Number: `**`545-4464`**\
`Type in a number (1-5): `**`2`**\
`Add Name and Number`\
`Name: `**`Jill`**\
`Number: `**`979-4654`**\
`Type in a number (1-5): `**`2`**\
`Add Name and Number`\
`Name: `**`Fred`**\
`Number: `**`132-9874`**\
`Type in a number (1-5): `**`1`**\
`Telephone Numbers:`\
`Name: Jill     Number: 979-4654`\
`Name: Joe      Number: 545-4464`\
`Name: Fred     Number: 132-9874`\
\
`Type in a number (1-5): `**`4`**\
`Lookup Number`\
`Name: `**`Joe`**\
`The number is 545-4464`\
`Type in a number (1-5): `**`3`**\
`Remove Name and Number`\
`Name: `**`Fred`**\
`Type in a number (1-5): `**`1`**\
`Telephone Numbers:`\
`Name: Jill     Number: 979-4654`\
`Name: Joe      Number: 545-4464`\
\
`Type in a number (1-5): `**`5`**

This program is similar to the name list earlier in the chapter on
lists. Here\'s how the program works. First the function `print_menu` is
defined. `print_menu` just prints a menu that is later used twice in the
program. Next comes the funny looking line `numbers = {}`. All that this
line does is to tell Python that `numbers` is a dictionary. The next few
lines just make the menu work. The lines

``` python
for x in numbers.keys():
    print("Name:", x, "\tNumber:", numbers[x])
```

go through the dictionary and print all the information. The function
`numbers.keys()` returns a list that is then used by the `for` loop. The
list returned by `keys()` is not in any particular order so if you want
it in alphabetic order it must be sorted. Similar to lists the statement
`numbers[x]` is used to access a specific member of the dictionary. Of
course in this case `x` is a string. Next the line
`numbers[name] = phone` adds a name and phone number to the dictionary.
If `name` had already been in the dictionary `phone` would replace
whatever was there before. Next the lines

``` python
if name in numbers:
    del numbers[name]
```

see if a name is in the dictionary and remove it if it is. The operator
`name in numbers` returns true if `name` is in `numbers` but otherwise
returns false. The line `del numbers[name]` removes the key `name` and
the value associated with that key. The lines

``` python
if name in numbers:
    print("The number is", numbers[name])
```

check to see if the dictionary has a certain key and if it does prints
out the number associated with it. Lastly if the menu choice is invalid
it reprints the menu for your viewing pleasure.

A recap: Dictionaries have keys and values. Keys can be strings or
numbers. Keys point to values. Values can be any type of variable
(including lists or even dictionaries (those dictionaries or lists of
course can contain dictionaries or lists themselves (scary right? :-)
))). Here is an example of using a list in a dictionary:

``` python
max_points = [25, 25, 50, 25, 100]
assignments = ['hw ch 1', 'hw ch 2', 'quiz   ', 'hw ch 3', 'test']
students = {'#Max': max_points}

def print_menu():
    print("1. Add student")
    print("2. Remove student")
    print("3. Print grades")
    print("4. Record grade")
    print("5. Print Menu")
    print("6. Exit")

def print_all_grades():
    print('\t', end=' ')
    for i in range(len(assignments)):
        print(assignments[i], '\t', end=' ')
    print()
    keys = list(students.keys())
    keys.sort()
    for x in keys:
        print(x, '\t', end=' ')
        grades = students[x]
        print_grades(grades)

def print_grades(grades):
    for i in range(len(grades)):
        print(grades[i], '\t', end=' ')
    print()

print_menu()
menu_choice = 0
while menu_choice != 6:
    print()
    menu_choice = int(input("Menu Choice (1-6): "))
    if menu_choice == 1:
        name = input("Student to add: ")
        students[name] = [0] * len(max_points)
    elif menu_choice == 2:
        name = input("Student to remove: ")
        if name in students:
            del students[name]
        else:
            print("Student:", name, "not found")
    elif menu_choice == 3:
        print_all_grades()
    elif menu_choice == 4:
        print("Record Grade")
        name = input("Student: ")
        if name in students:
            grades = students[name]
            print("Type in the number of the grade to record")
            print("Type a 0 (zero) to exit")
            for i in range(len(assignments)):
                print(i + 1, assignments[i], '\t', end=' ')
            print()
            print_grades(grades)
            which = 1234
            while which != -1:
                which = int(input("Change which Grade: "))
                which -= 1    #same as which = which - 1
                if 0 <= which < len(grades):
                    grade = int(input("Grade: "))
                    grades[which] = grade
                elif which != -1:
                    print("Invalid Grade Number")
        else:
            print("Student not found")
    elif menu_choice != 6:
        print_menu()
```

and here is a sample output:

`1. Add student`\
`2. Remove student`\
`3. Print grades`\
`4. Record grade`\
`5. Print Menu`\
`6. Exit`\
\
`Menu Choice (1-6): `**`3`**\
`       hw ch 1         hw ch 2         quiz            hw ch 3         test `\
`#Max    25              25              50              25              100 `\
\
`Menu Choice (1-6): `**`5`**\
`1. Add student`\
`2. Remove student`\
`3. Print grades`\
`4. Record grade`\
`5. Print Menu`\
`6. Exit`\
\
`Menu Choice (1-6): `**`1`**\
`Student to add: `**`Bill`**\
\
`Menu Choice (1-6): `**`4`**\
`Record Grade`\
`Student: `**`Bill`**\
`Type in the number of the grade to record`\
`Type a 0 (zero) to exit`\
`1   hw ch 1     2   hw ch 2     3   quiz        4   hw ch 3     5   test `\
`0               0               0               0               0 `\
`Change which Grade: `**`1`**\
`Grade: `**`25`**\
`Change which Grade: `**`2`**\
`Grade: `**`24`**\
`Change which Grade: `**`3`**\
`Grade: `**`45`**\
`Change which Grade: `**`4`**\
`Grade: `**`23`**\
`Change which Grade: `**`5`**\
`Grade: `**`95`**\
`Change which Grade: `**`0`**\
\
`Menu Choice (1-6): `**`3`**\
`       hw ch 1         hw ch 2         quiz            hw ch 3         test `\
`#Max    25              25              50              25              100`\
`Bill    25              24              45              23              95 `\
\
`Menu Choice (1-6): `**`6`**

Heres how the program works. Basically the variable `students` is a
dictionary with the keys being the name of the students and the values
being their grades. The first two lines just create two lists. The next
line `students = {'#Max': max_points}` creates a new dictionary with the
key {`#Max`} and the value is set to be `[25, 25, 50, 25, 100]` (since
thats what `max_points` was when the assignment is made) (I use the key
`#Max` since `#` is sorted ahead of any alphabetic characters). Next
`print_menu` is defined. Next the `print_all_grades` function is defined
in the lines:

``` python
def print_all_grades():
    print('\t',end=" ")
    for i in range(len(assignments)):
        print(assignments[i], '\t',end=" ")
    print()
    keys = list(students.keys())
    keys.sort()
    for x in keys:
        print(x, '\t',end=' ')
        grades = students[x]
        print_grades(grades)
```

Notice how first the keys are gotten out of the `students` dictionary
with the `keys` function in the line `keys = list(students.keys())`.
`keys` is an iterable, and it is converted to list so all the functions
for lists can be used on it. Next the keys are sorted in the line
`keys.sort()`. `for` is used to go through all the keys. The grades are
stored as a list inside the dictionary so the assignment
`grades = students[x]` gives `grades` the list that is stored at the key
`x`. The function `print_grades` just prints a list and is defined a few
lines later.

The later lines of the program implement the various options of the
menu. The line `students[name] = [0] * len(max_points)` adds a student
to the key of their name. The notation `[0] * len(max_points)` just
creates a list of 0\'s that is the same length as the `max_points` list.

The remove student entry just deletes a student similar to the telephone
book example. The record grades choice is a little more complex. The
grades are retrieved in the line `grades = students[name]` gets a
reference to the grades of the student `name`. A grade is then recorded
in the line `grades[which] = grade`. You may notice that `grades` is
never put back into the students dictionary (as in no
`students[name] = grades`). The reason for the missing statement is that
`grades` is actually another name for `students[name]` and so changing
`grades` changes `student[name]`.

Dictionaries provide an easy way to link keys to values. This can be
used to easily keep track of data that is attached to various keys.

