# A difficulty with lists

Discussion in 'Python' started by Mok-Kong Shen, Aug 6, 2012.

1. ### Mok-Kong ShenGuest

I ran the following code:

def xx(nlist):
print("begin: ",nlist)
nlist+=[999]
print("middle:",nlist)
nlist=nlist[:-1]
print("final: ",nlist)

u=[1,2,3,4]
print(u)
xx(u)
print(u)

and obtained the following result:

[1, 2, 3, 4]
begin: [1, 2, 3, 4]
middle: [1, 2, 3, 4, 999]
final: [1, 2, 3, 4]
[1, 2, 3, 4, 999]

As beginner I couldn't understand why the last line wasn't [1, 2, 3, 4].
Could someone kindly help?

M. K. Shen

Mok-Kong Shen, Aug 6, 2012

2. ### MRABGuest

On 06/08/2012 20:50, Mok-Kong Shen wrote:
> I ran the following code:
>
> def xx(nlist):
> print("begin: ",nlist)
> nlist+=[999]
> print("middle:",nlist)
> nlist=nlist[:-1]
> print("final: ",nlist)
>
> u=[1,2,3,4]
> print(u)
> xx(u)
> print(u)
>
> and obtained the following result:
>
> [1, 2, 3, 4]
> begin: [1, 2, 3, 4]
> middle: [1, 2, 3, 4, 999]
> final: [1, 2, 3, 4]
> [1, 2, 3, 4, 999]
>
> As beginner I couldn't understand why the last line wasn't [1, 2, 3, 4].
> Could someone kindly help?
>

This:

nlist+=[999]

appends to the list, making it [1, 2, 3, 4, 999].

This:

nlist=nlist[:-1]

gets a slice of the list and then binds it to the local name 'nlist'.

MRAB, Aug 6, 2012

On Monday, August 6, 2012 3:50:13 PM UTC-4, Mok-Kong Shen wrote:
> I ran the following code:
>
>
>
> def xx(nlist):
>
> print("begin: ",nlist)
>
> nlist+=[999]
>
> print("middle:",nlist)
>
> nlist=nlist[:-1]
>
> print("final: ",nlist)
>
>
>
> u=[1,2,3,4]
>
> print(u)
>
> xx(u)
>
> print(u)
>
>
>
> and obtained the following result:
>
>
>
> [1, 2, 3, 4]
>
> begin: [1, 2, 3, 4]
>
> middle: [1, 2, 3, 4, 999]
>
> final: [1, 2, 3, 4]
>
> [1, 2, 3, 4, 999]
>
>
>
> As beginner I couldn't understand why the last line wasn't [1, 2, 3, 4].
>
> Could someone kindly help?
>
>
>
> M. K. Shen

The list nlist inside of function xx is not the same as the variable u outside of the function: nlist and u refer to two separate list objects. Whenyou modify nlist, you are not modifying u. If you wanted the last line tobe [1, 2, 3, 4], you could use the code below:

#BEGIN CODE

def xx(nlist):

print("begin: ",nlist)

nlist+=[999]

print("middle:",nlist)

nlist=nlist[:-1]

print("final: ",nlist)

return nlist

u=[1,2,3,4]

print(u)

u = xx(u)

print(u)

#END CODE

Notice that I changed two things. First, the function xx(nlist) returns nlist. Secondly, u is reassigned to the result of xx(nlist).

On Monday, August 6, 2012 3:50:13 PM UTC-4, Mok-Kong Shen wrote:
> I ran the following code:
>
>
>
> def xx(nlist):
>
> print("begin: ",nlist)
>
> nlist+=[999]
>
> print("middle:",nlist)
>
> nlist=nlist[:-1]
>
> print("final: ",nlist)
>
>
>
> u=[1,2,3,4]
>
> print(u)
>
> xx(u)
>
> print(u)
>
>
>
> and obtained the following result:
>
>
>
> [1, 2, 3, 4]
>
> begin: [1, 2, 3, 4]
>
> middle: [1, 2, 3, 4, 999]
>
> final: [1, 2, 3, 4]
>
> [1, 2, 3, 4, 999]
>
>
>
> As beginner I couldn't understand why the last line wasn't [1, 2, 3, 4].
>
> Could someone kindly help?
>
>
>
> M. K. Shen

I've modified your code slightly so you can see what's happening with u in the middle of function xx. Take a look:

u=[1,2,3,4]

def xx(nlist):
print("xx(u)\n")
print("At first, u and nlist refer to the same list")
print("nlist: %s u: %s\n" % (nlist, u))

nlist+=[999]

print("nlist+=[999]\n")
print("The list has been modified in place. u and nlist are still equal")
print("nlist: %s u: %s\n" %(nlist, u))

nlist=nlist[:-1]

print("nlist=nlist[:1]\n")
print("Now nlist refers to a new list object in memory that was created by")
print("taking a slice of u. u and nlist are no longer equal.")
print("nlist: %s u: %s" %(nlist, u))

xx(u)

Here's the output:

xx(u)

At first, u and nlist refer to the same list
nlist: [1, 2, 3, 4] u: [1, 2, 3, 4]

nlist+=[999]

The list has been modified in place. u and nlist are still equal
nlist: [1, 2, 3, 4, 999] u: [1, 2, 3, 4, 999]

nlist=nlist[:1]

Now nlist refers to a new list object in memory that was created by
taking a slice of u. u and nlist are no longer equal.
nlist: [1, 2, 3, 4] u: [1, 2, 3, 4, 999]

Thank you, Rob Day, for explaining a some of what's happening behind the scenes.

5. ### Terry ReedyGuest

On 8/15/2012 5:58 PM, Rob Day wrote:

> The list nlist inside of function xx is not the same as the variable
> u outside of the function: nlist and u refer to two separate list
> objects. When you modify nlist, you are not modifying u.
> <http://mail.python.org/mailman/listinfo/python-list>

This is confused and wrong. The parameter *name* 'nlist' of function xx
is not the same as the *name* 'u' outside the function. The call xx(u)
binds nlist to the same object that u is bound to. At that point, the
two name *are* bound to the same list object. The statement
"nlist+=[999]" dodifying nlist *does* modify u. The subsequent
assignment statement "nlist=nlist[:-1]" rebinds 'nlist' to a *new* list
object. That new object gets deleted when the function returns. So the
rebinding is completely useless.

This sequence, modifying the input argument and then rebinding to a new

> Well - that's not quite true. Before calling the function, u is [1, 2,
> 3, 4] - but after calling the function, u is [1, 2, 3, 4, 999]. This is
> a result of using 'nlist += [999]' - the same thing doesn't happen if
> you use 'nlist = nlist+[999]' instead.
>
> I'm not completely aware of what's going on behind the scenes here, but

you got it right.

> I think the problem is that 'nlist' is actually a reference to a list
> object - it points to the same place as u.

Calling a python function binds parameter names to argument objects or
(for *args and **kwds parameters) a collection based on argument objects.

> When you assign to it within
> the function, then it becomes separate from u - which is why nlist =
> nlist+[999] and nlist = nlist[:-1] don't modify u - but if you modify
> nlist in place before doing that, such as by using +=, then it's still
> pointing to u, and so u gets modified as well.

--
Terry Jan Reedy

Terry Reedy, Aug 16, 2012

On Wednesday, August 15, 2012 8:21:22 PM UTC-4, Terry Reedy wrote:
> On 8/15/2012 5:58 PM, Rob Day wrote:
>
> Yeah, my apologies for any confusion I created. Although I suppose my explanation would be somewhat true for immutable objects since they can't be modified in-place (any modification at all would cause the creation of a new immutable object right?), I now understand that it is completely and totally wrong for mutable objects.

Thanks for the in-depth explanations, Terry and Rob. I feel like I have a much more solid grasp of what's going on behind the scenes after your analysis.
>

>
> > The list nlist inside of function xx is not the same as the variable

>
> > u outside of the function: nlist and u refer to two separate list

>
> > objects. When you modify nlist, you are not modifying u.

>
> > <http://mail.python.org/mailman/listinfo/python-list>

>
>
>
> This is confused and wrong. The parameter *name* 'nlist' of function xx
>
> is not the same as the *name* 'u' outside the function. The call xx(u)
>
> binds nlist to the same object that u is bound to. At that point, the
>
> two name *are* bound to the same list object. The statement
>
> "nlist+=[999]" dodifying nlist *does* modify u. The subsequent
>
> assignment statement "nlist=nlist[:-1]" rebinds 'nlist' to a *new* list
>
> object. That new object gets deleted when the function returns. So the
>
> rebinding is completely useless.
>
>
>
> This sequence, modifying the input argument and then rebinding to a new
>
>
>
>
> > Well - that's not quite true. Before calling the function, u is [1, 2,

>
> > 3, 4] - but after calling the function, u is [1, 2, 3, 4, 999]. This is

>
> > a result of using 'nlist += [999]' - the same thing doesn't happen if

>
> > you use 'nlist = nlist+[999]' instead.

>
> >

>
> > I'm not completely aware of what's going on behind the scenes here, but

>
>
>
> you got it right.
>
>
>
> > I think the problem is that 'nlist' is actually a reference to a list

>
> > object - it points to the same place as u.

>
>
>
> Calling a python function binds parameter names to argument objects or
>
> (for *args and **kwds parameters) a collection based on argument objects.
>
>
>
> > When you assign to it within

>
> > the function, then it becomes separate from u - which is why nlist =

>
> > nlist+[999] and nlist = nlist[:-1] don't modify u - but if you modify

>
> > nlist in place before doing that, such as by using +=, then it's still

>
> > pointing to u, and so u gets modified as well.

>
>
>
>
>
> --
>
> Terry Jan Reedy

7. ### ChengGuest

On Monday, August 6, 2012 12:50:13 PM UTC-7, Mok-Kong Shen wrote:
> I ran the following code:
>
>
>
> def xx(nlist):
>
> print("begin: ",nlist)
>
> nlist+=[999]
>
> print("middle:",nlist)
>
> nlist=nlist[:-1]
>
> print("final: ",nlist)
>
>
>
> u=[1,2,3,4]
>
> print(u)
>
> xx(u)
>
> print(u)
>
>
>
> and obtained the following result:
>
>
>
> [1, 2, 3, 4]
>
> begin: [1, 2, 3, 4]
>
> middle: [1, 2, 3, 4, 999]
>
> final: [1, 2, 3, 4]
>
> [1, 2, 3, 4, 999]
>
>
>
> As beginner I couldn't understand why the last line wasn't [1, 2, 3, 4].
>
> Could someone kindly help?
>
>
>
> M. K. Shen

When you pass a list (mutable object) to a function, the pointer to the list is passed to the function and the corresponding argument points to the same memory location as the pointer passed in. So in this case, nlist points to the same memory location which u points to when xx is called, i.e. nlist and u points to same memory location which contains [1,2,3,4].

nlist += [999] is equivalent to nlist.extend([999]). This statement addsthe argument list to the original list, i.e. the memory location pointed by nlist and u now contains [1,2,3,4,999]. So, print(u) after calling xx will print [1,2,3,4,999].

nlist += [999] is not the same as nlist = nlist + [999]. In the later case, nlist + [999] will create a new memory location containing the two lists combined and rebind nlist to the new location, i.e. nlist points to a new memory location that has [1,2,3,4,999]. So if nlist = nlist +[999] isused, the original memory location containing [1,2,3,4] is untouched, and print(u) after calling xx will print [1,2,3,4]

Cheng, Aug 20, 2012