Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKelly Musgrove
16,453 PointsReassigned list is still deleting items from the original list?
In our previous lessons, it was taught that removing items from a list that has been reassigned will not delete from the original list. Why is it that the 'players' list here is empty after I run the while loop, even though it's the reassigned 'roster' list that's being deleted from?
players = []
add_new_player = input("Would you like to add a player to the list? (Yes/No) ")
while add_new_player.upper() == "YES":
new_player = input("Enter the name of the player to add to the team: ")
players.append(new_player)
add_new_player = input("\nWould you like to add a player to the list? (Yes/No) ")
if add_new_player.upper() == "NO":
print("There are {} players on the team.".format(len(players)))
print(players)
player_number = 1
roster = players
while len(roster) > 0:
print("Player {}: {}".format(player_number, roster[0]))
del roster[0]
player_number += 1
print(players)
5 Answers
Ave Nurme
20,907 PointsHi Kelly
Have you heard of Python id-s and the id() function? If not, here's a short explanation for you:
- the id() function returns a unique id for the specified object.
- all objects in Python has its own unique id.
- the id is assigned to the object when it is created.
- the id is the object's memory address
So basically by roster = players
you are not actually copying the list rather than just reassigning it which means that the id stays the same for both of the objects roster
and players
.
I've added 3 lines of code into your code after where you make the reassignment to demonstrate this, please check the OUTPUT section as well, the list is empty indeed in the end:
players = []
add_new_player = input("Would you like to add a player to the list? (Yes/No) ")
while add_new_player.upper() == "YES":
new_player = input("Enter the name of the player to add to the team: ")
players.append(new_player)
add_new_player = input("\nWould you like to add a player to the list? (Yes/No) ")
if add_new_player.upper() == "NO":
print("There are {} players on the team.".format(len(players)))
print(players)
player_number = 1
roster = players
print(f'\nThe id of players is {id(players)}')
print(f'The id of roster is {id(roster)}')
print('Both players and roster have the same id\n')
while len(roster) > 0:
print("Player {}: {}".format(player_number, roster[0]))
del roster[0]
player_number += 1
print(players)
"""
OUTPUT:
Would you like to add a player to the list? (Yes/No) yes
Enter the name of the player to add to the team: Mike
Would you like to add a player to the list? (Yes/No) yes
Enter the name of the player to add to the team: Matt
Would you like to add a player to the list? (Yes/No) no
There are 2 players on the team.
['Mike', 'Matt']
The id of players is 2191336012544
The id of roster is 2191336012544
Both players and roster have the same id
Player 1: Mike
Player 2: Matt
[]
"""
If you wish your original list players
to be untouched you need to make a copy of it (EDIT: this means the lists will have their own unique id-s). There are many ways to do this. You can use slicing for instance like this roster = players[:]
. This way your players
list will not be affected.
I made the some changes to your code, used slicing and the original list stays unaffected. The list in the end is not empty:
players = []
add_new_player = input("Would you like to add a player to the list? (Yes/No) ")
while add_new_player.upper() == "YES":
new_player = input("Enter the name of the player to add to the team: ")
players.append(new_player)
add_new_player = input("\nWould you like to add a player to the list? (Yes/No) ")
if add_new_player.upper() == "NO":
print("There are {} players on the team.".format(len(players)))
print(players)
player_number = 1
roster = players[:]
print(f'\nThe id of players is {id(players)}')
print(f'The id of roster is {id(roster)}')
print('Players and roster have a different id\n')
while len(roster) > 0:
print("Player {}: {}".format(player_number, roster[0]))
del roster[0]
player_number += 1
print(players)
"""
OUTPUT:
Would you like to add a player to the list? (Yes/No) yes
Enter the name of the player to add to the team: Mike
Would you like to add a player to the list? (Yes/No) yes
Enter the name of the player to add to the team: Matt
Would you like to add a player to the list? (Yes/No) no
There are 2 players on the team.
['Mike', 'Matt']
The id of players is 2435709532928
The id of roster is 2435741032960
Players and roster have a different id
Player 1: Mike
Player 2: Matt
['Mike', 'Matt']
"""
Does this help? I tried to be as clear as possible by explaining this :-)
Jeff Muday
Treehouse Moderator 28,720 PointsWhat Ave said above is correct. And you can check the id()
of the lists to see if these point to the same memory structure.
The short answer is-- lists in Python are mutable. When you assign roster = players
both point to the same memory location. You need to make a copy of the list instead.
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
Below is an implicit (shallow) copy using list slice method. Which works in Python 2.x and 3.x
roster = players[:]
Another more explict copy method is a "cast" instantiation. You explicitly tell Python you want a NEW list object
roster = list(players)
Below is a PEP20 compliant copy. It is more explicit but does the same thing as the slice method. This works only in Python 3.x
roster = players.copy()
Kelly Musgrove
16,453 PointsThank you! This is very helpful as well.
Ave Nurme
20,907 PointsHi Jeff
Thank you for commenting on my post and making things even clearer. The last part of your comment where you show how to make explicit copies of a list was really helpful to me personally. As the Zen of Python states 'Explicit is better than implicit'. Thanks again!
Ave Nurme
20,907 PointsHappy to help, Kelly!
Chaquayla Halmon
1,797 PointsThis post has helped me a lot thanks to both Jeff and Ave. Also Kelly for bringing this problem up. I didn't have the same problem but my question was still answered along the way. Very helpful.
Kelly Musgrove
16,453 PointsKelly Musgrove
16,453 PointsThanks so much! I had not learned about id's in Python... until now! I really appreciate the thorough explanation!