1

I recently did an exam for university and I got asked what would be the output of this program:

def fun(x):
    y=x
    x.append(4)
    print(str(x)+" "+str(y))

fun(["one","two",3,5.0])

I answered that the y list would be ["one","two", 3,5.0] and after appending 4 to it, the x list would be equal to the same but with a 4 at the end of it. To my surprise, when I printed both lists, they were equal even though the x list update was performed after establishing an equality between both lists. Why did this happen?

Thank you

Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
OCA
  • 111
  • 2
  • 8
  • possible duplicate of [How to clone or copy a list in Python?](http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python) – awesoon Jan 02 '15 at 07:09

5 Answers5

3

You have given reference if list x to y. So any change in list x would also affect list y.

y=x

For example:

>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> x
['one', 'two', 3, 4]
>>> y
['one', 'two', 3, 4]

Here both x and y have same identity.

>>> x is y
True
>>> id(x)
3073118540L
>>> id(y)
3073118540L

You can better understand this using swampy module:

>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> lump.object_diagram()

enter image description here


What you were expecting can be achieved by copying the list x to list y like this:

>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> x.pop()
5.0
>>> x
['one', 'two', 3]
>>> y
['one', 'two', 3, 5.0]

So by copying the content from x to y, they don't hold the same identity:

>>> id(x)
3073240428L
>>> id(y)
3073240588L
>>> x is y
False

Using swampy:

>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> lump.draw_object()
>>> lump.object_diagram()

enter image description here

For better explanation visit here How do I copy an object in Python?

Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
1

Actually x and y are labels that reference to object so when you assign y=x you crate 2 reference to one object , so when you change one of them you change the main object .

Also you may note that x , y are local variables when you made inplace changes like append you changed the main object , but if you use assignment python create a new object :

>>> def fun(x):
...     y=x
...     x=x+[3]
...     print(str(x)+" "+str(y))
... 
>>> fun(["one","two",3,5.0])
['one', 'two', 3, 5.0, 3] ['one', 'two', 3, 5.0]

in-place changes to objects do not classify names as locals; only actual name assignments do. For instance, if the name L is assigned to a list at the top level of a module, a statement L = X within a function will classify L as a local, but L.append(X) will not. In the latter case, we are changing the list object that L references, not L itself— L is found in the global scope as usual, and Python happily modifies it without requiring a global (or nonlocal ) declaration. As usual, it helps to keep the distinction between names and objects clear: changing an object is not an assignment to a name.(from learning python by mark lutz)

class A:
  global L
  L=[1,2]
  def b(self):
     L=[0,0]
     return L
  def c(self):
     L.append(5)
     return L

a=A()
print a.b()

print a.c()

result :

[0, 0]
[1, 2, 5]
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • could you provide an example how this looks if a name L is assigned to a list at the top of the module ? – Praneeth Jun 12 '15 at 14:46
0

Because list are mutable objects. see Python Data Model

In [1]: a = [1]

In [3]: b = a

In [4]: b
Out[4]: [1]

In [5]: b.append(2)

In [6]: a
Out[6]: [1, 2]

In [7]: b
Out[7]: [1, 2]

In [8]: id(a), id(b)
Out[8]: (140260765233376, 140260765233376)
Vishnu Upadhyay
  • 5,043
  • 1
  • 13
  • 24
0

Because the name y is bound to the same list as x

y = x

This is a great drawing of how that looks:

 x   y
 |  /
 | /
["one", "two", 3, 5.0]

x.append(4)

 x   y
 |  /
 | /
["one", "two", 3, 5.0, 4]
jamylak
  • 128,818
  • 30
  • 231
  • 230
0

You can try following example. It will help you to get differences between assignment operator and method like copy(shallow), deepcopy.

>>> import copy
>>> l1 = [1,2, [1,2]]
>>> l1
[1, 2, [1, 2]]
#Create l2, l3, l4 by copy, deepcopy method and normal assignment.
>>> l2 = copy.copy(l1)
>>> l3 = copy.deepcopy(l1)
>>> l4 = l1
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2]]
#-----------------------Now Append value to l1
>>> l1.append(9)
>>> l1
[1, 2, [1, 2], 9]
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2], 9]
#-----------------------Now Append value to l1[2]
>>> l1[2].append(5)
>>> l1
[1, 2, [1, 2, 5], 9]
>>> l2
[1, 2, [1, 2, 5]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2, 5], 9]
#------------------------
Vivek Sable
  • 9,938
  • 3
  • 40
  • 56