[Tutor] Standard way to append to a list? ['+=' is in-place concatenation]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Wed Apr 16 21:00:02 2003


On Thu, 17 Apr 2003, Magnus [iso-8859-1] Lyck=E5 wrote:

> Secondly, using "l =3D l + [4]" or the shorter form "l +=3D [4]", you are
> doing the following:
>
> 1. To start with, you have a list object containing [1,2,3]
> 2. Then you create a new list object containing [4].
> 3. With your assignment you create a new list object, and
>     place the sum of the two lists, i.e. [1,2,3,4] in that.
> 4. As you rebind the variable name "l" from the list
>     containing [1,2,3] to the one containing [1,2,3,4], you
>     will reduce the reference count on the list containing
>     [1,2,3]. If no other variables etc references that list,
>     it will be garbage collected now (or perhaps a little
>     later if you are running Jython.)
> 5. The list containing [4] will also be garbage collected as
>     soon as the assignment is done.


Hi Magnus,


Clarification on the second form: the expression:

    l +=3D [4]

is called an 'in-place concatenation', and for lists, this actually calls
the extend() method!  For those with a C bent, here's the relevant code
from the Python source:


/***/
static PyObject *
list_inplace_concat(PyListObject *self, PyObject *other)
{
        other =3D PySequence_Fast(other, "argument to +=3D must be iterable=
");
        if (!other)
                return NULL;

        if (listextend_internal(self, other) < 0)
                return NULL;

        Py_INCREF(self);
        return (PyObject *)self;
}
/***/




Wait a minute... I can't seem to prove this by overriding the extend()
method!

###
>>> class mylist(list):
=2E..     def extend(self, other):
=2E..         print "I'm extend()!"
=2E..         list.extend(self, other)
=2E..
>>> l =3D mylist([1, 2, 3])
>>> l +=3D [4]
>>> l
[1, 2, 3, 4]
>>> l.extend([4])
I'm extend()!
###

Weird!  I'm using Python 2.2.1 here; can anyone confirm if this is
happening with Python 2.2.2 or 2.3alpha?  Does this look like a bug to
anyone else?  ... Checking SourceForge... nope, I don't see anything about
this.


Sorry for getting sidetracked... *grin* I'd better check that in my spare
time.


Anyway the 'in-place concatenation' statement,

    left_hand_side +=3D right_hand_size

is not just syntactic sugar for

    left_hand_side =3D left_hand_side + right_hand_size

Python often does take advantage of the fact that the left hand side is
being mutated.


Hope this helps!