1

I'm having troubles understanding dictionaries and for loop. I have this example that takes a nested dictionary representing a playlist of songs. On the first example the code runs just fine, but when I try to create a function and try to clean up the code. It keeps saying index out of range. Can anybody throw their 2 cents.

Example playlist from a JSON file:

playlist = {
        'title': 'faves',
        ' author': 'Me', 
        'songs': [
        {
            'title': 'song1',
            'artist': ['john', 'smith'],
            'genre': 'Pop',
            'duration' : 3.23
        },
        {
            'title': 'song2',
            'artist': ['john2'],
            'genre': 'Rock',
            'duration' : 3.45
        },
        {
            'title': 'song3',
            'artist': ['john3', 'smith3'],
            'genre': 'Jazz',
            'duration' : 2.45
        }
    ]
}

This first code byte works well and print the right strings.

sa =  f" and {song['artist'][1]}"
for song in playlist['songs']:
    print(f"{song['title']} by {song['artist'][0]}{sa if len(song['artist']) >= 2 else ''}, runtime: {song['duration']}, genre: {song['genre']}")
  • song1 by john and smith3, runtime: 3.23, genre: Pop
  • song2 by john2, runtime: 3.45, genre: Rock
  • song3 by john3 and smith3, runtime: 2.45, genre: Jazz

But here when I try to run this it says index out of range. It's calling artist_two, but is not supposed to do that unless there is more than one artist for a song.

def print_playlist(songs):
    print(songs)
    for song in songs:

        title = song['title']
        duration = song['duration']
        genre = song['genre']
        artists = song['artist']
        artist_one = song['artist'][0]
        artist_two = song['artist'][1]
        sa =  f" and {artist_two}"


        print(f"{title} by {artist_one}{sa if len(artists) >=2 else ''}, runtime: {duration}, genre: {genre}")

print_playlist(playlist['songs'])
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 2
    So add a check for it? Your code right now is assuming that there's always 2 artists. `artist_two = song['artist'][1]` will always be executed – UnholySheep Nov 07 '18 at 19:03
  • yes, but I'm not calling the variable right away, i'm using (sa) to insert the second artist only if there are more than one artist for the same song. my confusion come because it somehow works, on the first code, but them I create variables, it throws an error – Yoan Herrera Nov 07 '18 at 19:16
  • Python does not perform lazy evaluation. When the interpreter reaches `artist_two = song['artist'][1]` it will always be evaluated, regardless of whether you actually use the variable `artist_two` or not – UnholySheep Nov 07 '18 at 19:33
  • That makes sense. Thanks so much for the help. This is my first time trying to code something without following a tutorial and its a little confusing. I was able to use .join() to concatenate the list as Zack suggested bellow. – Yoan Herrera Nov 07 '18 at 19:51

2 Answers2

1

You can use this method to make a string of the names with " and " in between them.

artist_list=["John","Smith"]

y=" and ".join(str(x) for x in artist_list)

print(y)

This give the output of John and Smith

And if you make the artist list: ["John","Smith","Dave"] Your output will look like John and Smith and Dave

As mentioned in the comment above, you are assuming there are always at least 2 elements in the artist_list. You should rather use an approach like mine that I found from Concatenate item in list to strings

Zack Tarr
  • 851
  • 1
  • 8
  • 28
0

Thank you Zack Tarr

final code looks like

def print_playlist(songs):
for song in songs:

    title = song['title']
    duration = song['duration']
    genre = song['genre']
    artists = song['artist']

    artist_plus = " and ".join( artist for artist in artists)


    print(f" {title} by {artist_plus if len(artists) >= 2 else artists[0]}, runtime: {duration}, genre: {genre}")

print_playlist(playlist['songs'])