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 trial

Python Python Collections (Retired) Slices Introduction To Slices

I don't understand the difference between list2 = list1[:] and list2 = list1 Could you explain? Thank you.

It looks like both lines do the same.

3 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Adding a second answer to better explain my first one. The problem with my first answer is my example. I went and used ints, which are immutable. I would have had the same problem if I had used a string or a tuple, since they're also immutable. When it comes to mutable types, like lists and dictionaries, my example is correct. See the following:

>>> a = 5
>>> id(a)
4303119104
>>> b = a
>>> id(b)
4303119104
>>> a = 10
>>> id(a)
4303119264
>>> id(b)
4303119104

Again, these are immutable variables. So their id(), the spot they point to in memory, changes. Now let's try it with a mutable variable.

>>> list1 = [1, 2, 3]
>>> list2 = list1
>>> id(list1)
4316698760
>>> id(list2)
4316698760
>>> list1.append(4)
>>> list2
[1, 2, 3, 4]
>>> list1 = [4, 2, 3, 1]
>>> list2
[1, 2, 3, 4]

If we modify a mutable type in place, then all references to it will be updated as well, since they're just pointing to the same place. That's why I want you to make a copy of the list.

Thanks for making me investigate this more!

Now it's totally clear :) Thank you.

Daewon Kim
Daewon Kim
15,016 Points

I get it now. Thank you.

Dago Romer
Dago Romer
1,769 Points

Just adding a comment to clarify as reading your second code block confused me for a second. When you do list1 = [4,3,2,1] it actually deletes the old list1 variable, creates a brand new one with a different id and new content. That's why list1 = [1,2,3,4] didn't update list2, but doing list1.something() uses the existing variable so it will update list2.

Am I right in my assumption?

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Dago Romer exactly. Lists are mutable so calling methods on them (like list1.append(4) or list2.sort()) changes them in place. But when I re-created list1, it's a brand new object with a new place in memory.

Conor Igoe
Conor Igoe
14,047 Points

Dago Romer just to check your check (:P) did you mean "That's why list1 = [4,3,2,1] ..." instead of "That's why list1 = [1,2,3,4] ..." ?

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Everything Python is passed by reference. So if I do

>>> a = 5
>>> b = a
>>> a = 10

Then b will be equal to 10 because b just points to, or has a reference to, a.

We want to have a new, distinct copy of a list. There are two ways to do this. list2 = list1.copy() will copy list1 into list2. That's fine and everything, but it's longer to type than the second way and it just doesn't feel as clean.

list2 = list1[:] will put all of the contents of list1 into list2. This is less typing and most Python programmer's preferred way of copying a list.

Kenneth, thank you for answer. And now I'm more confused than before.

tried on http://teamtreehouse.com/workspaces/1814152

"""

a = 5
b = a
b
5
a = 10
a
10
b
5 """

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Huh, I am too :) I'll investigate a bit more and then update my answer.

Jeff Muday
Jeff Muday
Treehouse Moderator 28,716 Points

For me, I think readability is improved by using "list()" as an object constructor rather than using [:] slice as syntactic magic rule. Though, as a fan of Kenneth's work and a math-lover, I could be convinced to read [:] notation as returning a "non-parametric-independent-slice" of a list.

>>> a = [4,2,3,1]
>>> id(a)
42738192
>>> b = list(a) # reads like a list object constructor
>>> b
[4,2,3,1]
>>> id(b)
4274132 # b has a different id than a
>>> b.sort()
>>> b
[1,2,3,4] # b, now neatly sorted
>>> a
[4,2,3,1] # a's order left untouched

So I tried the following and it may answer your question

>>> list1 = [5, 3, 7, 4, 2, 1, 6]
>>> list1
[5, 3, 7, 4, 2, 1, 6]
>>> list2 = list1
>>> list2
[5, 3, 7, 4, 2, 1    6]
>>> list2.sort()
>>> list2
[1, 2, 3, 4, 5, 6, 7]
>>> list1
[1, 2, 3, 4, 5, 6, 7]

Notice how I only performed a sort() on list2? But list1 was also sorted. This is because list2 really only points to the memory location that list1 is stored in and this is because we made a shallow copy of list1 and stored it into list2.

Now see what happens when i use the [:] option, we just learned:

>>> list1 = [ 5,3,7,4,2,1,6]
>>> list1
[5, 3, 7, 4, 2, 1, 6]
>>> list2 = list1[:]
>>> list2
[5, 3, 7, 4, 2, 1, 6]
>>> list2.sort()
>>> list2
[1, 2, 3, 4, 5, 6, 7]
>>> list1
[5, 3, 7, 4, 2, 1, 6]

list2 = list1[:] tells python to make a deep copy of list1 and store it into list2. For more information on this behavior, do a google search on shallow vs deep copy. It is a behavior you will find in c/c++ and perhaps many other languages.

Hope this helps and I didn't make things more confusing Tim McCune