Carly's Clippers - list comprehension

Hi, I’m working on the Carly’s Clippers project (https://www.codecademy.com/courses/learn-python-3/projects/python-carlys-clippers) and I’m stuck in step 12.

Here’s my entire code, step 12 starting on line 25.

hairstyles = ["bouffant", "pixie", "dreadlocks", "crew", "bowl", "bob", "mohawk", "flattop"] prices = [30, 25, 40, 20, 20, 35, 50, 35] last_week = [2, 3, 5, 8, 4, 4, 6, 2] total_price = 0 for price in prices: total_price += price average_price = total_price / len(prices) print("Average Haircut Price:", average_price) new_prices = [price - 5 for price in prices] print("New Prices:", new_prices) total_revenue = 0 for i in range(len(hairstyles)): total_revenue += prices[i] * last_week[i] print("Total Revenue:", total_revenue) average_daily_revenue = total_revenue / 7 print("Average Daily Revenue:", average_daily_revenue) # My initial code: what's wrong here? cuts_under_30 = [hairstyles[i] for new_prices[i] in new_prices if new_prices[i] < 30] print(cuts_under_30) # Revised: cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30] print(cuts_under_30)

I’m confused why my code here doesn’t work and prints out ‘flattop’ 4 times instead.

# My initial code: what's wrong here?
cuts_under_30 = [hairstyles[i] for new_prices[i] in new_prices if new_prices[i] < 30]
print(cuts_under_30)

# Revised:
cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]
print(cuts_under_30)

Is it because I used the list new_prices and didn’t create a new list using range()?
Why should it be a problem?

Many thanks in advance! :slightly_smiling_face:

This is occurring because of the way you are trying to use the variable ‘i’. Without any sort of logic to modify ‘i’ it will be a static number that has already been defined after the for loop on line 18.

1 Like

On line 15 when you print the new prices, you will see:

New Prices: [25, 20, 35, 15, 15, 30, 45, 30]

As noted by ktsotras, when your loop (on line 18) finishes, then i will hold the last value assigned to it.
After the last iteration of the loop for i in range(len(hairstyles)), the last value assigned to i will be 7.

# My initial code: what's wrong here?
cuts_under_30 = [hairstyles[i] for new_prices[i] in new_prices if new_prices[i] < 30]
print(cuts_under_30)

In your list comprehension above, you are iterating over the new_prices list but the loop variable chosen by you is new_prices[i].

In the first iteration, the first element of new_prices i.e. 25 will be assigned to new_prices[i] which is equivalent to the assignment new_prices[7] = 25. Then the if condition, checks whether new_prices[7] < 30. If so, hairstyles[i] i.e. hairstyles[7] is appended to the cuts_under_30 list. There are four values in new_prices which are less than 30, so hairstyles[7] i.e. the string "flattop" will be appended to cuts_under_30 four times. Consequently, the output seen by you will be:

['flattop', 'flattop', 'flattop', 'flattop']

To better understand what is going on, try turning your list comprehension into a for loop (with print statements for debugging):

print(new_prices)
cuts_under_30 = []
for new_prices[i] in new_prices:
    print(new_prices)
    if new_prices[i] < 30:
        cuts_under_30.append(hairstyles[i])
print(cuts_under_30)

// Output
// new_prices before loop
[25, 20, 35, 15, 15, 30, 45, 30]

// new_prices during loop
// Note what is happening to new_prices[7]
[25, 20, 35, 15, 15, 30, 45, 25]
[25, 20, 35, 15, 15, 30, 45, 20]
[25, 20, 35, 15, 15, 30, 45, 35]
[25, 20, 35, 15, 15, 30, 45, 15]
[25, 20, 35, 15, 15, 30, 45, 15]
[25, 20, 35, 15, 15, 30, 45, 30]
[25, 20, 35, 15, 15, 30, 45, 45]
[25, 20, 35, 15, 15, 30, 45, 45]

// cuts_under_30 after loop
['flattop', 'flattop', 'flattop', 'flattop']

Both your use of i and the choice of new_prices[i] as the loop variable is problematic.
You could use a variable such as

for price in new_prices:

This will iterate over new_prices properly, but the problem is that the hairstyles are in a different list, and just the price won’t allow you to pick out the corresponding hairstyle.

Instead, looping over the index as you did in

# Revised:
cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]

works. By looping over the index, you can use the same index i to pair the price with the corresponding hairstyle by targeting the correct elements from the new_prices and hairstyles lists respectively.

2 Likes