Dictionaries allow us to associate a value with a name (generally called a key). It's more general than that, but that's probably the most common use. 

A common way to construct a dictionary to use the brace notation:

>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> d
{'one': 1, 'three': 3, 'two': 2}

Notice that dictionaries are not ordered. That's fine, because they don't use numeric indices, they use keys.

As with lists, we can find out how many key-value pairs are in a dictionary using:

>>> len(d)
3

Accessing data in a dictionary is done similarly to lists:

>>> d['three']
3

as is changing it:

>>> d['three'] = 'not3'
>>> d
{'one': 1, 'three': 'not3', 'two': 2}

Adding a key/value pair to a dictionary is the same as modifying one:

>>> d['four'] = 4
>>> d
{'four': 4, 'one': 1, 'two': 2, 'three': 'not3'}

To remove from a dictionary we use the del function:

>>> del(d['three'])
>>> d
{'four': 4, 'one': 1, 'two': 2}

Finally, we can check if a dictionary contains a specific key:

>>> 'one' in d
True
>>> 'three' not in d
True
>>> 'three' in d
False

Formats - Songbook

So we have notes represented by tuples that we can put together in a list to make a song. What if we want multiple songs? We could have each in a separate variable. Let's add the additional requirement that we want to connect an I2C OLED display to show a list of songs that we can select from. Having songs in separate variables means that everything has to be hardcoded. That's seldom a good idea. What we'd like is to have things stored in such a way that we just have to add a song and have the menu automatically be updated to reflect it. We can do this by storing them in a dictionary, keyed by name (edited for brevity):

songbook = {'Twinkle Twinkle': [(C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), ...],
                         
            'ItsyBitsy Spider': [(G4, 0.5), (C4, 0.5), (C4, 0.5), (C4, 0.5), (D4, 0.5), ...],

            'Old MacDonald': [(G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), ...]
           }

With that done, we can get the names of the songs by songbook.keys(). This isn't a list, although it can be used for some list-like things. It can't be indexed, however. We need to convert it to a list in order to be able to do that: list(songbook.keys()). While we're at it, we should go ahead and sort it so that it will display in alphabetical order: sorted(list(songbook.keys())).

Here is the complete code:

# SPDX-FileCopyrightText: 2018 Dave Astels for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import board
from adafruit_debouncer import Debouncer
import busio as io
import digitalio
import pwmio
import adafruit_ssd1306

i2c = io.I2C(board.SCL, board.SDA)
reset_pin = digitalio.DigitalInOut(board.D11)
oled = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin)
select = digitalio.DigitalInOut(board.D7)
select.direction = digitalio.Direction.INPUT
select.pull = digitalio.Pull.UP
button_select = Debouncer(select)
play = digitalio.DigitalInOut(board.D9)
play.direction = digitalio.Direction.INPUT
play.pull = digitalio.Pull.UP
button_play = Debouncer(play)

C4     = 261
C_SH_4 = 277
D4     = 293
D_SH_4 = 311
E4     = 329
F4     = 349
F_SH_4 = 369
G4     = 392
G_SH_4 = 415
A4     = 440
A_SH_4 = 466
B4     = 493

# pylint: disable=line-too-long
songbook = {'Twinkle Twinkle': [(C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 1.0), (0, 0.5),
                                (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (D4, 0.5), (C4, 0.5), (0, 0.5),
                                (G4, 0.5), (G4, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5),
                                (G4, 0.5), (G4, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5),
                                (C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 1.0), (0, 0.5),
                                (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (D4, 0.5), (C4, 0.5), (0, 0.5)],

            'ItsyBitsy Spider': [(G4, 0.5), (C4, 0.5), (C4, 0.5), (C4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (C4, 0.5), (D4, 0.5), (E4, 0.5), (C4, 0.5), (0, 0.5),
                                 (E4, 0.5), (E4, 0.5), (F4, 0.5), (G4, 0.5), (G4, 0.5), (F4, 0.5), (E4, 0.5), (F4, 0.5), (G4, 0.5), (E4, 0.5), (0, 0.5)],

            'Old MacDonald': [(G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5),
                              (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5),
                              (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5),
                              (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5),
                              (D4, 0.5), (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5),
                              (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5),
                              (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5),
                              (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5),
                              (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5)]
           }
# pylint: enable=line-too-long

def play_note(note):
    if note[0] != 0:
        pwm = pwmio.PWMOut(board.D12, duty_cycle = 0, frequency=note[0])
        # Hex 7FFF (binary 0111111111111111) is half of the largest value for a 16-bit int,
        # i.e. 50%
        pwm.duty_cycle = 0x7FFF
    time.sleep(note[1])
    if note[0] != 0:
        pwm.deinit()


def play_song(songname):
    for note in songbook[songname]:
        play_note(note)


def update(songnames, selected):
    oled.fill(0)
    line = 0
    for songname in songnames:
        if line == selected:
            oled.text(">", 0, line * 8)
        oled.text(songname, 10, line * 8)
        line += 1
    oled.show()


selected_song = 0
song_names = sorted(list(songbook.keys()))
while True:
    button_select.update()
    button_play.update()
    update(song_names, selected_song)
    if button_select.fell:
        print("select")
        selected_song = (selected_song + 1) % len(songbook)
    elif button_play.fell:
        print("play")
        play_song(song_names[selected_song])

This guide was first published on Jul 13, 2018. It was last updated on Jul 13, 2018.

This page (Dictionary) was last updated on Mar 18, 2023.

Text editor powered by tinymce.