Newbie question: Allocation vs references

Discussion in 'Python' started by Jan Danielsson, Jun 2, 2005.

  1. Hello all,

    Behold:

    ----------
    a = [ 'Foo', 'Bar' ]
    b = [ 'Boo', 'Far' ]
    q = [ a, b ]

    print q[0][0]
    print q[1][1]

    a[0] = 'Snoo'
    b[1] = 'Gnuu'

    print q[0][0]
    print q[1][1]
    ----------

    This will output:
    Foo
    Far
    Snoo
    Gnuu

    I assume it does so because q stores _references_ to a and b. How
    would do I do if I want to copy the list? I.e. I want the output from
    the code above to be:

    Foo
    Far
    Foo
    Far

    ...even if a[0] = 'Snoo' and b[1] = 'Gnuu' remain where they are.

    Or, better yet, how do I store a and b in q, and then tell Python
    that I want a and b to point to new lists, without touching the contents
    in q?

    C equivalent of what I want to do:
    -----------
    a = calloc(n, size);
    prepare(a)

    q[0] = a;

    a = calloc(n, size); // new list; 'q' is unaffected if I change 'a'
    -----------
     
    Jan Danielsson, Jun 2, 2005
    #1
    1. Advertising

  2. Jan Danielsson

    rzed Guest

    Jan Danielsson <> wrote in
    news:429efdbf$:

    > Hello all,
    >
    > Behold:
    >
    > ----------
    > a = [ 'Foo', 'Bar' ]
    > b = [ 'Boo', 'Far' ]
    > q = [ a, b ]
    >
    > print q[0][0]
    > print q[1][1]
    >
    > a[0] = 'Snoo'
    > b[1] = 'Gnuu'
    >
    > print q[0][0]
    > print q[1][1]
    > ----------
    >
    > This will output:
    > Foo
    > Far
    > Snoo
    > Gnuu
    >
    > I assume it does so because q stores _references_ to a and b.
    > How
    > would do I do if I want to copy the list? I.e. I want the output
    > from the code above to be:
    >


    If your original assigment to q were:
    q = [ a[:], b[:] ]
    .... you would have copies of a and b, so that:

    >>> a = [ 'Foo', 'Bar' ]
    >>> b = [ 'Boo', 'Far' ]
    >>> q = [ a[:], b[:] ]
    >>> print q[0][0]

    Foo
    >>> print q[1][1]

    Far
    >>>
    >>> a[0] = 'Snoo'
    >>> b[1] = 'Gnuu'
    >>>
    >>> print q[0][0]

    Foo
    >>> print q[1][1]

    Far

    > Foo
    > Far
    > Foo
    > Far
    >
    > ..even if a[0] = 'Snoo' and b[1] = 'Gnuu' remain where they are.
    >
    > Or, better yet, how do I store a and b in q, and then tell
    > Python
    > that I want a and b to point to new lists, without touching the
    > contents in q?


    That's easier:
    >>> a = [ 'Foo', 'Bar' ]
    >>> b = [ 'Boo', 'Far' ]
    >>> q = [a,b]
    >>> a = ['Splee','Hoongk']
    >>> b = ['Blik','Poit']
    >>> print q[0][0]

    Foo
    >>> print q[1][1]

    Far

    You've stuck the 'a' and 'b' labels on new objects this way. The
    original objects would vanish except that there is still a reference
    to them through the 'q' list.

    >
    > C equivalent of what I want to do:
    > -----------
    > a = calloc(n, size);
    > prepare(a)
    >
    > q[0] = a;
    >
    > a = calloc(n, size); // new list; 'q' is unaffected if I change
    > 'a' -----------




    --
    rzed
     
    rzed, Jun 2, 2005
    #2
    1. Advertising

  3. On 2005-06-02 14:43:40, Jan Danielsson wrote:

    > a = [ 'Foo', 'Bar' ]
    > b = [ 'Boo', 'Far' ]
    > q = [ a, b ]


    > Or, better yet, how do I store a and b in q, and then tell Python
    > that I want a and b to point to new lists, without touching the contents
    > in q?


    There are several ways to create a copy of a list:

    a1 = a[:] # new copy, sliced from 0 to end
    a2 = list(a) # create a new list object out of any sequence
    import copy
    a3 = copy.copy(a) # use the copy module


    So you could do for example:

    q1 = [ list(a), list(b) ]
    q2 = [ a[:], b[:] ]
    q3 = [ list(x) for x in (a,b)]


    Note that the copy module also has a function deepcopy that will make
    copies at all levels. So if you had:

    q = [a,b]
    q1 = copy.deepcopy(q2)


    every list in q1, even the inner "a" and "b" will be new copies. Note
    that non-mutables such as "Foo" and "Bar" are NOT copied, but as they
    cannot be changed, that doesn't matter.

    --
    Stian Søiland Work toward win-win situation. Win-lose
    Trondheim, Norway is where you win and the other lose.
    http://soiland.no/ Lose-lose and lose-win are left as an
    exercise to the reader. [Limoncelli/Hogan]
    Og dette er en ekstra linje
     
    Stian =?iso-8859-1?Q?S=F8iland?=, Jun 2, 2005
    #3
  4. Stian Søiland wrote:
    > There are several ways to create a copy of a list:

    [snip]
    > a2 = list(a) # create a new list object out of any sequence


    I'll just point out that FWIW, this is by far my favorite idiom of the
    ones offered because it applies to pretty much all the builtin container
    types:

    py> d = {1:42, -37:0}
    py> d2 = dict(d)
    py> d == d2, d is d2
    (True, False)
    py> s = set(['a', 'd', 'e'])
    py> s2 = set(s)
    py> s == s2, s is s2
    (True, False)
    py> L = [3.14, 0.707]
    py> L2 = list(L)
    py> L == L2, L is L2
    (True, False)

    STeVe
     
    Steven Bethard, Jun 2, 2005
    #4
    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. Roger Leigh
    Replies:
    8
    Views:
    447
    Karl Heinz Buchegger
    Nov 17, 2003
  2. Replies:
    3
    Views:
    461
    Victor Bazarov
    Nov 10, 2004
  3. Ken
    Replies:
    24
    Views:
    3,876
    Ben Bacarisse
    Nov 30, 2006
  4. chris
    Replies:
    6
    Views:
    993
    chris
    Oct 28, 2005
  5. Bjarke Hammersholt Roune
    Replies:
    14
    Views:
    1,194
    Bjarke Hammersholt Roune
    Mar 6, 2011
Loading...

Share This Page