Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #26652 > unrolled thread

A difficulty with lists

Started byMok-Kong Shen <mok-kong.shen@t-online.de>
First post2012-08-06 21:50 +0200
Last post2012-08-20 13:43 -0700
Articles 7 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  A difficulty with lists Mok-Kong Shen <mok-kong.shen@t-online.de> - 2012-08-06 21:50 +0200
    Re: A difficulty with lists MRAB <python@mrabarnett.plus.com> - 2012-08-06 21:19 +0100
    Re: A difficulty with lists Madison May <worldpeaceagentforchange@gmail.com> - 2012-08-15 14:12 -0700
      Re: A difficulty with lists Terry Reedy <tjreedy@udel.edu> - 2012-08-15 20:21 -0400
        Re: A difficulty with lists Madison May <worldpeaceagentforchange@gmail.com> - 2012-08-16 06:46 -0700
    Re: A difficulty with lists Madison May <worldpeaceagentforchange@gmail.com> - 2012-08-15 16:56 -0700
    Re: A difficulty with lists Cheng <chbeh88@googlemail.com> - 2012-08-20 13:43 -0700

#26652 — A difficulty with lists

FromMok-Kong Shen <mok-kong.shen@t-online.de>
Date2012-08-06 21:50 +0200
SubjectA difficulty with lists
Message-ID<jvp75j$opr$1@news.albasani.net>
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

[toc] | [next] | [standalone]


#26655

FromMRAB <python@mrabarnett.plus.com>
Date2012-08-06 21:19 +0100
Message-ID<mailman.3029.1344284341.4697.python-list@python.org>
In reply to#26652
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'.

[toc] | [prev] | [next] | [standalone]


#27113

FromMadison May <worldpeaceagentforchange@gmail.com>
Date2012-08-15 14:12 -0700
Message-ID<16702a22-6ce3-4120-bbcc-9649e1717130@googlegroups.com>
In reply to#26652
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.  When you modify nlist, you are not modifying u.  If you wanted the last line to be [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).

[toc] | [prev] | [next] | [standalone]


#27126

FromTerry Reedy <tjreedy@udel.edu>
Date2012-08-15 20:21 -0400
Message-ID<mailman.3334.1345076503.4697.python-list@python.org>
In reply to#27113
On 8/15/2012 5:58 PM, Rob Day wrote:

 > Madison May 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 
object, is bad code.

> 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

[toc] | [prev] | [next] | [standalone]


#27162

FromMadison May <worldpeaceagentforchange@gmail.com>
Date2012-08-16 06:46 -0700
Message-ID<480fc764-16bd-4ce8-8518-fe0366c8c25e@googlegroups.com>
In reply to#27126
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. 
> 
>  > Madison May 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 
> 
> object, is bad code.
> 
> 
> 
> > 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

[toc] | [prev] | [next] | [standalone]


#27122

FromMadison May <worldpeaceagentforchange@gmail.com>
Date2012-08-15 16:56 -0700
Message-ID<275392ae-09e2-469d-a9e3-43a9f50eece5@googlegroups.com>
In reply to#26652
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.

[toc] | [prev] | [next] | [standalone]


#27530

FromCheng <chbeh88@googlemail.com>
Date2012-08-20 13:43 -0700
Message-ID<66aafdc3-7ea5-4401-859b-89cd5bf268a8@googlegroups.com>
In reply to#26652
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 adds the 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] is used, the original memory location containing [1,2,3,4] is untouched, and print(u) after calling xx will print [1,2,3,4]

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web