Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The order of iterable de-referencing in assignment?

41 views
Skip to first unread message

Shiyao Ma

unread,
Aug 24, 2016, 6:55:32 AM8/24/16
to
Hi,

Given a = [1, 2]

a.extend(a) makes a = [1,2, 1,2]

One might guess a.extend(a) would turn into an infinite loop. It turns out here Python first gets all the items of `a' and then append them to `a', so the infinite loop is avoided.

My question is, is there any doc on the behavior of things like this?

Another related example might be:
a[:] = a
Hopefully Python first gets all the items on the *right* side and then assigns them to the left.

Regards.

Chris Angelico

unread,
Aug 24, 2016, 7:01:19 AM8/24/16
to
On Wed, Aug 24, 2016 at 8:54 PM, Shiyao Ma <i...@introo.me> wrote:
> Given a = [1, 2]
>
> a.extend(a) makes a = [1,2, 1,2]
>
> One might guess a.extend(a) would turn into an infinite loop. It turns out here Python first gets all the items of `a' and then append them to `a', so the infinite loop is avoided.
>

Be careful: doing the same in Python may not behave that way.

>>> a = [1,2]
>>> for x in a: a.append(x)
...
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>> len(a)
6370805

That right there, folks, is an infinite loop.

ChrisA

Marko Rauhamaa

unread,
Aug 24, 2016, 7:10:09 AM8/24/16
to
Shiyao Ma <i...@introo.me>:

> Given a = [1, 2]
>
> a.extend(a) makes a = [1,2, 1,2]
>
> One might guess a.extend(a) would turn into an infinite loop. It turns
> out here Python first gets all the items of `a' and then append them
> to `a', so the infinite loop is avoided.

Functionally, Python's lists are not linked lists but, rather, vectors.

> My question is, is there any doc on the behavior of things like this?

No. It should be here:

<URL: https://docs.python.org/3/reference/datamodel.html>

It only states:

The items of a list are arbitrary Python objects.

and inexplicably muddies the waters by continuing:

Lists are formed by placing a comma-separated list of expressions in
square brackets. (Note that there are no special cases needed to form
lists of length 0 or 1.)

(which has nothing whatsoever to do with the data model).


Marko

Chris Angelico

unread,
Aug 24, 2016, 7:17:57 AM8/24/16
to
On Wed, Aug 24, 2016 at 9:03 PM, Joaquin Alzola
<Joaquin...@lebara.com> wrote:
>>> One might guess a.extend(a) would turn into an infinite loop. It turns out here Python first gets all the items of `a' and then append them to `a', so the infinite loop is avoided.
>>>> a = [1,2]
>>>> for x in a: a.append(x)
>>...
>>^CTraceback (most recent call last):
> > File "<stdin>", line 1, in <module>
>>KeyboardInterrupt
>>>>> len(a)
>>6370805
>
>>That right there, folks, is an infinite loop.
>
> If I am correct python points out an infinite loop with the "...", just pointing to more information.

That's true of self-referential objects and circular references:

>>> a = [1, 2]
>>> a.append(a)
>>> a
[1, 2, [...]]

In this case, it's not an infinite loop or anything; it's simply an
object that references itself:

>>> id(a)
139945904550344
>>> [id(x) for x in a]
[9241344, 9241376, 139945904550344]

The list has three elements, one of which is the list itself. Same
applies if the list has a reference to something else which has a
reference to the original list, or anything along those lines.

But "a.extend(a)" isn't quite like that. In its purest form, it means
the same as the 'for' loop that I showed above, but... well, this
comment from the CPython sources says exactly what I'm thinking of:

Objects/listobject.c:795

/* Special cases:
1) lists and tuples which can use PySequence_Fast ops
2) extending self to self requires making a copy first
*/

> This email is confidential and may be subject to privilege. If you are not the intended recipient, please do not copy or disclose its content but contact the sender immediately upon receipt.
>

This email is confident and may be subject to white privilege, black
privilege, and privileges of other colours. If you are not the
intended recipient, please contact a lawyer and tell him that email
footers are unenforceable.

ChrisA

Random832

unread,
Aug 24, 2016, 10:10:39 AM8/24/16
to
On Wed, Aug 24, 2016, at 07:17, Chris Angelico wrote:
> Objects/listobject.c:795
>
> /* Special cases:
> 1) lists and tuples which can use PySequence_Fast ops
> 2) extending self to self requires making a copy first
> */

And, of course, it is a special case - a.extend(iter(a)) is enough to
break it.

Frankly I'm not sure why bother to implement it when anyone who
legitimately wants to do it can simply do a *= 2.

Joaquin Alzola

unread,
Aug 24, 2016, 9:41:20 PM8/24/16
to
>> One might guess a.extend(a) would turn into an infinite loop. It turns out here Python first gets all the items of `a' and then append them to `a', so the infinite loop is avoided.
>>> a = [1,2]
>>> for x in a: a.append(x)
>...
>^CTraceback (most recent call last):
> File "<stdin>", line 1, in <module>
>KeyboardInterrupt
>>>> len(a)
>6370805

>That right there, folks, is an infinite loop.

If I am correct python points out an infinite loop with the "...", just pointing to more information.
0 new messages