Python Arena
Step 1 of 4

Objects in lists and dictionaries

An object of a class you wrote can go anywhere a number or a string can: into a variable, a list, a dictionary or a function call. To Python, your classes are types just like the ones it has built in. 5 is an int, "hi" is a str, Song("Slow River", 302) is a Song, and all of them are objects. You have already kept your own objects in variables and lists and given them to functions. This part of the course looks at what really happens when you do, starting with lists and dictionaries of objects.

A list of objects

Here a playlist is a list of Song objects. The loop takes the songs one at a time, and song.title reaches the title of the song the loop is at:

class Song:
    def __init__(self, title, seconds):
        self.title = title
        self.seconds = seconds


playlist = []
playlist.append(Song("Morning Light", 215))
playlist.append(Song("Slow River", 302))
playlist.append(Song("Neon Rain", 187))

total = 0
for song in playlist:
    print(song.title)
    total += song.seconds

print("Total length:", total, "seconds")
Output
Morning Light
Slow River
Neon Rain
Total length: 704 seconds

Each Song(...) call creates a new object, and append puts it at the end of the list. In the loop, song is a Song object, so everything a song has is there behind the dot.

Finding the right object

A function can look through a list of objects and return one of them. Returning the whole object, not just its title, lets the caller use whatever it needs from it:

class Song:
    def __init__(self, title, seconds):
        self.title = title
        self.seconds = seconds

    def __str__(self):
        return f"{self.title} ({self.seconds} s)"


def longest(songs):
    best = songs[0]
    for song in songs:
        if song.seconds > best.seconds:
            best = song
    return best


playlist = [Song("Morning Light", 215), Song("Slow River", 302), Song("Neon Rain", 187)]
winner = longest(playlist)
print(winner)
print("Title only:", winner.title)
Output
Slow River (302 s)
Title only: Slow River

best starts as the first song and is replaced whenever a longer one comes along. The comparison is between song.seconds and best.seconds, two numbers. Comparing the songs themselves doesn't work, because Python has no idea what would make one song "greater" than another:

class Song:
    def __init__(self, title, seconds):
        self.title = title
        self.seconds = seconds


first = Song("Morning Light", 215)
second = Song("Slow River", 302)
print(first > second)
Python stops with
Traceback (most recent call last):
  File "main.py", line 9, in <module>
    print(first > second)
          ^^^^^^^^^^^^^^
TypeError: '>' not supported between instances of 'Song' and 'Song'

When you see this error, decide which attribute you meant to compare, and compare that.

Objects in a dictionary

Objects can be the values of a dictionary too. Here each song has a code, as on a jukebox:

class Song:
    def __init__(self, title, seconds):
        self.title = title
        self.seconds = seconds


jukebox = {}
jukebox["A1"] = Song("Morning Light", 215)
jukebox["B7"] = Song("Slow River", 302)

code = "B7"
print("Now playing:", jukebox[code].title)
Output
Now playing: Slow River

jukebox[code] is a Song object, so .title can come right after it.

Your task

Challenge 1 of 3

The program should print the total running time of the movies in the list. Fill in the blanks so it prints:

Total: 371 minutes

Challenge 2

Write a function cheapest(products). It gets a list of Product objects and returns the cheapest product: the object itself, not its name. You can assume the list has at least one product and that no two products cost the same.

For example, this code:

items = [Product("Tea", 3.5), Product("Bread", 2.25), Product("Cheese", 6.0)]
print(cheapest(items))

prints:

Bread (2.25)

Challenge 3

What does this program print? Type each line it prints.