2012-03-27 11 views
3

Python nicht unterstützen ein Tupel zu einer Liste hinzu:Warum kann ich einer Liste mit dem Operator '+' in Python kein Tupel hinzufügen?

>>> [1,2,3] + (4,5,6) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can only concatenate list (not "tuple") to list 

Was sind die Nachteile für die Bereitstellung einer solchen Unterstützung in der Sprache? Beachten Sie, dass ich erwarte, dass dies symmetrisch ist: [1, 2] + (3, 4) und (1, 2) + [3, 4] würden beide zu einer brandneuen Liste [1, 2, 3, 4] bewerten. Mein Grundgedanke ist, dass, sobald jemand operator + auf eine Mischung aus Tupeln und Listen angewendet hat, diese wahrscheinlich erneut (sehr wahrscheinlich in demselben Ausdruck) ausgeführt werden, sodass wir die Liste auch bereitstellen könnten, um zusätzliche Conversions zu vermeiden.

Hier ist meine Motivation für diese Frage.

Es passiert ziemlich oft, dass ich kleine Sammlungen habe, die ich lieber als Tupel speichern möchte, um versehentliche Änderungen zu vermeiden und die Leistung zu verbessern. Ich muss dann solche Tupel mit Listen kombinieren, und jede davon in eine Liste umwandeln zu müssen, macht einen sehr hässlichen Code.

Beachten Sie, dass += oder extend in einfachen Fällen funktionieren kann. Aber im Allgemeinen, wenn ich einen Ausdruck habe

Ich weiß nicht, welche dieser Tupel und welche Listen sind. Also entweder ich muss alles auf Listen konvertieren:

columns = list(default_columns) + list(columns_from_user) + list(calculated_columns) 

oder benutzen itertools:

columns = list(itertools.chain(default_columns, columns_from_user, calculated_columns)) 

Beide Lösungen sind hässlicher als eine einfache Summe; und die chain kann auch langsamer sein (da sie die Eingänge ein Element auf einmal durchlaufen muss).

+2

Wie wäre es, einfach konsistent zu sein? Verwenden Sie Tupel oder Verwendungslisten, aber nicht beide. –

+0

Wenn es _at all_ unterstützt würde, würde ich zustimmen, dass das das beste Verhalten wäre, aber ich denke, wenn jemand '2 + 'abc' macht, wollen sie eindeutig' '2abc'' also warum nicht zulassen, etc. etc. - - Es ist zu viel Interpretation. Explizit ist besser als implizit. – agf

+1

Sie könnten einfach "itertools.chain" verwenden, um Ihre Sachen zu verketten und niemals '+' stattdessen verwenden. – hochl

Antwort

10

Dies wird nicht unterstützt, da der + Operator symmetrisch soll. Welcher Rückgabetyp würden Sie erwarten?Der Python Zen umfasst die Regel

In the face of ambiguity, refuse the temptation to guess. 

Folgende Werke, aber:

a = [1, 2, 3] 
a += (4, 5, 6) 

Es gibt keine Zweideutigkeit, welche Art hier zu verwenden.

+0

Ich würde erwarten, dass die Rückkehr eine Liste sein würde, seit ich + Operator benutze, ist es wahrscheinlich, dass ich tun muss es wieder. Siehe mein Update zu der Frage. – max

+3

@max: Ich kann nicht sehen, warum das immer eine Liste zurückgeben sollte. Ich bin froh, dass Python in einer solchen Situation einen Fehler verursacht, und ich bin zuversichtlich, dass sich das nicht ändern wird. –

+0

@max: Sie haben gefragt * Warum unterstützt Python das Hinzufügen eines Tupels zu einer Liste * nicht? IMHO, Svens Antwort nagelt diese Frage. – MattH

1

Sie können das += Operator, ob das hilft:

>>> x = [1,2,3] 
>>> x += (1,2,3) 
>>> x 
[1, 2, 3, 1, 2, 3] 

Sie auch explizit die Liste Konstruktor verwenden können, aber wie Sie erwähnt haben, könnte die Lesbarkeit leiden:

>>> list((1,2,3)) + list((1,2,3)) 
[1, 2, 3, 1, 2, 3] 
+0

Es tut, wenn ich nur ein Tupel habe hinzufügen. Ich habe oft mehrere Objekte, einige Tupel, einige Listen. – max

+0

Seine Frage ist "warum". – agf

2

Warum Python doesn 's unterstützt das Hinzufügen eines anderen Typs: Die einfache Antwort ist, dass sie verschiedene Typen haben, was ist, wenn Sie versuchen, einen iterierbaren Wert hinzuzufügen und eine Liste zu erwarten? Ich selbst würde gerne ein anderes iterables zurückgeben. Überlegen Sie auch, ['a','b']+'cd' was sollte die Ausgabe sein? unter Berücksichtigung explizit ist besser als implizit alle solche impliziten Konvertierungen sind nicht erlaubt.

Um diese Einschränkung zu umgehen, verwenden Sie extend Methode der Liste, um alle iterierbaren z.

l = [1,2,3] 
l.extend((4,5,6)) 

Wenn Sie viele Liste hinzufügen müssen/Tupel Schreiben Sie eine Funktion

def adder(*iterables): 
    l = [] 
    for i in iterables: 
     l.extend(i) 
    return l 

print adder([1,2,3], (3,4,5), range(6,10)) 

Ausgang:

[1, 2, 3, 3, 4, 5, 6, 7, 8, 9] 
+1

Er weiß, wie es geht, er will wissen, warum er es nicht mit '+' machen kann. – agf

+0

@agf: * "und jede von ihnen in die Liste zu konvertieren, macht einen sehr hässlichen Code" *. Nein, anscheinend nicht, weil '.extend()' nichts konvertieren wird. –

+1

@RikPoggi Er möchte einen langen Ausdruck wie '[1] + (2,) + (3,) + [4] + (5,)' gleichzeitig ohne Umwandlung oder "Kette" oder Ähnliches machen können das ohne Einfachheit. Jeder Code, der 'extend' verwendet, um dies in einer Zeile zu tun, ist hässlicher als nur dieser Additionsausdruck. – agf