1

I have the following code and I'm wondering why it returns the same list instead of a copy:

x = [2,1,3]
y = x
y.sort()
print y
print x

Why does this return the same sorted list?

locoboy
  • 38,002
  • 70
  • 184
  • 260
  • "why it returns the same list"? Because that's the rule for `=`. I'm unclear on what you're asking? Are you asking for the Python definition of `=`? – S.Lott Aug 01 '11 at 21:46

6 Answers6

5

Because it's modified in-place.

Python lists have reference semantics, meaning that when you assign a list to another variable, they're actually pointing at the same list.

If you want to make a copy, do this:

x = [2,1,3]
y = x[:]
y.sort()
print y
print x

The slice notation does cause the list (in this case, the entire list, though you can make a small modification to ask for a particular sublist) to be copied.

Jeremy Roman
  • 16,137
  • 1
  • 43
  • 44
  • 1
    Everything in Python has reference semantics unless you go out of your way to fake value semantics. – Karl Knechtel Aug 01 '11 at 21:47
  • Hmm...you are correct. Numbers just appear to have value semantics because they are immutable. Alright, I'll remove the offending sentence. – Jeremy Roman Aug 01 '11 at 21:49
  • 1
    Numbers only *appear* to have value semantics; when you say `a=a+b`, you're creating a new number that is the sum and reassigning the name `a` to that sum. The old contents of `a` are still in memory, waiting to be garbage collected. – Mark Ransom Aug 01 '11 at 21:50
  • Mark: Yes, this is what I was referring to in my comment just above yours. As I said, corrected. – Jeremy Roman Aug 01 '11 at 21:50
  • wait, so what is happening when you say `x=1 \n y=x \n x=2` ? – locoboy Aug 01 '11 at 21:54
  • You're creating a value `1`, then assigning it to `x`. Then you're assigning the same value to `y`. Then you're creating another new value `2`, and changing x to point at the `2` rather than the `1`. Whereas when you use the `sort()` method, you're asking a particular value to mutate itself in-place. Fortunately, the numbers don't have any such methods, so you can treat them as though they have value semantics. – Jeremy Roman Aug 01 '11 at 21:55
  • I see that makes sense. So that's what you mean when py is reference based but 'appears' to not be in the case just presented. – locoboy Aug 01 '11 at 21:58
4

You are dealing with references in Python. The statement y = x makes y point to the same thing as x, so changes to y are reflected in x (because they point to the same underlying list).

You can change a copy by doing:

y = list(x) # make a copy of the list so we can change y without disturbing x
y.sort()

or

y = sorted(x) # return a new sorted copy of what is in x
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
2

x is the name of ("reference to") the list (object). The line

y=x

merely makes y another name for the same list. If you want to copy the list, use one of

y = x[:]
y = list(x)

(The first syntax is just an ordinary list slice, but with both the start and the end values left out, meaning that it takes the entire list.)

Note that a list is a list of objects, and copying the list will not copy the objects. If you want that behaviour — a deep copy — you must do so explicitly with

import copy
y = copy.deepcopy(x)

Naturally, this will be slower.

Katriel
  • 120,462
  • 19
  • 136
  • 170
0

Assigning a list to another variable in Python creates a reference, so any changes you make to the reference will show up in the original. If you want a copy that will not alter the original, do this:

y = x[:]
Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
0

Because you only copy the reference.

For instruction on how to clone the list ('deep copy'),see: How to clone or copy a list?

Community
  • 1
  • 1
markijbema
  • 3,985
  • 20
  • 32
0

When you say y = x, you're really just assigning another name (y) to the contents of x. If x is a mutable value and you do something to change it, you change the one-and-only copy that has 2 different names.

A common way to prevent this is to assign to a slice, which is always a copy of the original list.

y = x[:]
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622