A difficulty with lists

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

  1. 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
    #1
    1. Advertising

  2. Mok-Kong Shen

    MRAB Guest

    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
    #2
    1. Advertising

  3. Mok-Kong Shen

    Madison May Guest

    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).
    Madison May, Aug 15, 2012
    #3
  4. Mok-Kong Shen

    Madison May Guest

    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.
    Madison May, Aug 16, 2012
    #4
  5. Mok-Kong Shen

    Terry Reedy Guest

    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
    Terry Reedy, Aug 16, 2012
    #5
  6. Mok-Kong Shen

    Madison May Guest

    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
    Madison May, Aug 16, 2012
    #6
  7. Mok-Kong Shen

    Cheng Guest

    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
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JustSomeGuy

    Sorting lists of lists...

    JustSomeGuy, Jun 17, 2004, in forum: C++
    Replies:
    0
    Views:
    300
    JustSomeGuy
    Jun 17, 2004
  2. Jon Slaughter

    lists of lists

    Jon Slaughter, Dec 13, 2004, in forum: C++
    Replies:
    4
    Views:
    398
    Buster
    Dec 13, 2004
  3. Charlotte Henkle

    Counter for items in lists in lists?

    Charlotte Henkle, Sep 25, 2004, in forum: Python
    Replies:
    8
    Views:
    385
    Charlotte Henkle
    Sep 26, 2004
  4. robin
    Replies:
    10
    Views:
    525
    Dave Hansen
    Apr 12, 2006
  5. =?UTF-8?B?w4FuZ2VsIEd1dGnDqXJyZXogUm9kcsOtZ3Vleg==

    List of lists of lists of lists...

    =?UTF-8?B?w4FuZ2VsIEd1dGnDqXJyZXogUm9kcsOtZ3Vleg==, May 8, 2006, in forum: Python
    Replies:
    5
    Views:
    378
    =?UTF-8?B?w4FuZ2VsIEd1dGnDqXJyZXogUm9kcsOtZ3Vleg==
    May 15, 2006
Loading...

Share This Page