[Python-bugs-list] [ python-Bugs-575536 ] Concatenating a tuple to a list

noreply@sourceforge.net noreply@sourceforge.net
Sun, 30 Jun 2002 12:42:58 -0700


Bugs item #575536, was opened at 2002-06-29 19:18
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=575536&group_id=5470

Category: Python Interpreter Core
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Dan Grassi (dgrassi)
>Assigned to: Guido van Rossum (gvanrossum)
Summary: Concatenating a tuple to a list

Initial Comment:
"a=a+b" is not the same as "a+=b" if a is a list and b is a tuple.  See the code below.

This has been tested on 2.2.1 MacPython, 2.2 MachoPython and 2.2 Python on an Alpha.

Augmented assignment (+=) with a list on the LHS allows a tuple on the RHS.  Standard assignment does not.

This seems intuitively wrong.

--- test code ---
a=[1]
b=(2,)

print 1,type(a), a
print 1,type(b), b
c=a+b

print 2,type(a), a
print 2,type(b), b
a=a+b

print 3,type(a), a
print 3,type(b), b
a+=b

print 4,type(a), a
print 4,type(b), b

Below is the execution results of the above:

>>>
>>> a=[1]
>>> b=(2,)
>>>
>>> print 1,type(a), a
1 <type 'list'> [1]
>>> print 1,type(b), b
1 <type 'tuple'> (2,)
>>> c=a+b
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: can only concatenate list (not "tuple") to list
>>>
>>> print 2,type(a), a
2 <type 'list'> [1]
>>> print 2,type(b), b
2 <type 'tuple'> (2,)
>>> a=a+b
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: can only concatenate list (not "tuple") to list
>>>
>>> print 3,type(a), a
3 <type 'list'> [1]
>>> print 3,type(b), b
3 <type 'tuple'> (2,)
>>> a+=b
>>>
>>> print 4,type(a), a
4 <type 'list'> [1, 2]
>>> print 4,type(b), b
4 <type 'tuple'> (2,)
>>>


----------------------------------------------------------------------

>Comment By: Raymond Hettinger (rhettinger)
Date: 2002-06-30 14:42

Message:
Logged In: YES 
user_id=80475

GvR,  please pronounce.
1. liberalize list_concat to match list_inplace_concat,
2. restrict list_inplace_concat to match list_concat, or
3. declare it fine the way it is.

While you're at it, pronounce for tuples also.  Timbot 
makes a good argument that they should be left alone.


----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2002-06-30 14:37

Message:
Logged In: YES 
user_id=80475

I have zero emotional attachment to this. Do whatever you 
think best: accept it, close it, or assign to GvR to get a 
pronouncement for alltime.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-06-30 14:31

Message:
Logged In: YES 
user_id=31435

Dueling edits.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-06-30 14:25

Message:
Logged In: YES 
user_id=31435

The intent was that list.__iadd__ correspond exactly to 
list.extend().  There's no need to hypergeneralize 
list.__add__() too:  it's a feature that people who don't 
want to get surprised by Martin-like examples can avoid 
them by using plain + for lists.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2002-06-30 14:08

Message:
Logged In: YES 
user_id=80475

One other thought -- list.__add__ 's  behavior should 
correspond closely to list.extend():

>>> a = [1]
>>> a.extend((2,3))
>>> a.extend({4:5})
>>> a
[1, 2, 3, 4]

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-06-30 14:04

Message:
Logged In: YES 
user_id=31435

This is all intentional.  Lists choose to implement

list += whatever

as a synonym for

list.extend(whatever)

and whatever can be any iterable object in both.  It's A 
Feature that mutable objects can choose to do something 
different for += than for +.

Trying to make tuples do this too is a bad idea -- there is 
no tuple.extend(), and there can't be because tuples are 
immutable.

Lists and tuples differ here.  If they were the same thing, 
there wouldn't be much point to having both <wink>.

I recommend closing as WontFix, although it's quite 
possible the docs could be improved (haven't looked).

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2002-06-30 14:00

Message:
Logged In: YES 
user_id=80475

Agreed. My first instinct was to restrict list_inplace_concat
() rather than liberalize list_concat(); however, it is already 
out in the wild and code may be relying on it.

One change or the other should be made since the docs 
promise that 'a op= b'  is equivalent to 'a = a op b' unless 
specifically overriden or when get/set attr is used to 
access 'a'.

Your example highlights the weirdness that can ensue; 
however, I think we already started down that road when 
everything was made iterable and, therefore, substitutable 
into weird combinations:

>>> zip([1], 'hallo', {1:2})
[(1, 'h', 1)]

----------------------------------------------------------------------

Comment By: Martin v. Löwis (loewis)
Date: 2002-06-30 13:43

Message:
Logged In: YES 
user_id=21627

I'm not so sure that the current += behaviour is desirable.
It means that

a=[1]
a+="hallo"
a+={1:2}

is possible, which should be a TypeError, IMO.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2002-06-30 11:35

Message:
Logged In: YES 
user_id=80475

Confirmed.  The behavior of list_inplace_concat diverged 
from list_concat.

See attached patch. Recommend applying to Py2.3 only 
since inconsistency isn't a bug.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=575536&group_id=5470