Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Python Collections (Retired) Lists Redux Manipulating Lists

Srikanth Srinivas
Srikanth Srinivas
1,465 Points

Why doesn't it delete the sublist from the larger list?

I tried to delete the sublist from the bigger list but it never seems to work. Isn't the sublist an item inside the larger list of type list? Shouldn't it consider the sublist as an item and delete the item i.e.. the sublist?

Im kinda confused, it doesn't seem to delete it and i know that theres something wrong with my code.

lists.py
the_list = ["a", 2, 3, 1, False, [1, 2, 3]]

# Your code goes below here
the_list.insert(0,(the_list.pop(3)))
for item in the_list:
  if type(item) == str:
    the_list.remove(item)
  elif type(item) == bool:
    the_list.remove(item)
  elif type(item) == list:
    the_list.remove(item)

1 Answer

Gunhoo Yoon
Gunhoo Yoon
5,027 Points

In a nutshell the problem happens because the_list that is operated by for loop keeps shrinking as each item gets removed. It is critical that you know what it mean by list being mutable.

Here's simple debugging code.

your_code.py
the_list = ["a", 2, 3, 1, False, [1, 2, 3]]

#Feel free to run this in your work space.
the_list.insert(0,(the_list.pop(3)))

for item in the_list:
  # Simple debugging line.
  print("{} being evaluated from {}".format(item, the_list))
  if type(item) == str:
    the_list.remove(item)
  elif type(item) == bool:
    the_list.remove(item)
  elif type(item) == list:
    the_list.remove(item)

Here's the result from above.

debug.py
# 1 being evaluated from [1, 'a', 2, 3, False, [1, 2, 3]]                                          
# a being evaluated from [1, 'a', 2, 3, False, [1, 2, 3]]                                          
# 3 being evaluated from [1, 2, 3, False, [1, 2, 3]]                                               
# False being evaluated from [1, 2, 3, False, [1, 2, 3]]   

Did you notice something weird? 2 and [1, 2, 3] never gets evaluated. Why? take a look at this code which is replication of the bug you made. Also, your loop only runs 4 times where it is supposed to run 6 times.

replication.py
the_list = ["a", 2, 3, 1, False, [1, 2, 3]]


the_list.insert(0,(the_list.pop(3)))

index = 0
while(len(the_list) != index):

  if type(the_list[index]) == str:
    the_list.remove(the_list[index])
  elif type(the_list[index]) == bool:
    the_list.remove(the_list[index])
  elif type(the_list[index]) == list:
    the_list.remove(the_list[index])

  index += 1

print(the_list) # [1, 2, 3, [1, 2, 3]]

The index doesn't reflect your mutated list correctly and results in skipping elements. This problem happens because the target list that you are referring to is keep changing. So to fix problem make an independent copy of your list and loop on that copy.

fixed.py
# Leave this as it is
the_list = ["a", 2, 3, 1, False, [1, 2, 3]]

# You will learn what [ : ] in a lesson or two.
# The side effect of it is creating a new copy of list.
copied_list = the_list[:]

# Your code goes below here
the_list.insert(0,(the_list.pop(3)))

# Now loop on referring to copied_list
for item in copied_list:

  # But remove item from original_list since you want that.
  if type(item) == str:
    the_list.remove(item)
  elif type(item) == bool:
    the_list.remove(item)
  elif type(item) == list:
    the_list.remove(item)

There is still downside to this but for this case it works okay.

I've also answered same question and this is more verbal so check it out if above codes don't make sense to you check it out

Srikanth Srinivas
Srikanth Srinivas
1,465 Points

I dont understand. Why are we making a copy of the list? i don't get why we can't just use the same list.

Gunhoo Yoon
Gunhoo Yoon
5,027 Points

My question to you is did you learn about list is mutable and do you understand what it means? If not all of the answer above will just confuse you. I won't assume you know.

Here's easier real life abstraction on what happened.

Let's say you have three boxes with a number 0, 1, 2.

Each box has single item pie, cookie, snake.

So your box looks like this

[0: pie, 1: cookie, 2: snake]

Now you are checking inventory to make sure every item is in the box starting from 0.

When you are about to check the box some thief eats pie without you knowing and moves cookie and snake to

box 0 and box 1 to pretend nothing happened. Now your inventory will look like this.

[0: cookie, 1: snake, 2: empty]

So when you are about to check box 0 you see cookie when that should've been pie. But you record cookie anyway since that's what you saw.

That is what happened to your program.

For loop is you checking boxes and remove() is the thief. Obviously this doesn't reflect what happened in Python precisely but that's the logic on why your program behaves weirdly.

So creating copy is similar to having inventory item list so you can keep track on what happened.