2012-12-16 28 views
6

Gefunden interessante Sache in Python (2.7), die nie zuvor erwähnt.Liste erweitert seltsames Verhalten

Dies:

a = [] 
a += "a" 

funktioniert und das Ergebnis ist:

>>> a 
>>> ["a"] 

Aber

a = [] 
a = a + "a" 

gibt

>>> TypeError: can only concatenate list (not "str") to list 

Kann jemand erklären warum? Danke für deine Antworten.

+0

'+' und '+ =' sind verschiedene Operationen, auch wenn sie in vielen Situationen das gleiche zu tun scheinen. –

+1

'+ =' verhält sich wie extend() in Python-Listen (inplace add) und der andere heißt binary add. –

Antwort

11

Python unterscheidet zwischen den Operatoren + und += und bietet separate Hooks für diese; __add__ und __iadd__. Der list() Typ stellt einfach eine andere Implementierung für Letzteres bereit.

Es ist effizienter für Listen, diese separat zu implementieren; __add__ muss eine komplett neue Liste zurückgeben, während __iadd__ nur self verlängern kann, dann self zurückgeben.

Im C-Code wird __iadd__ von list_inplace_concat(), implementiert, die einfach listextend() nennt, oder, in Python-Code, [].extend(). Letzteres erfordert irgendeine Sequenz, von Entwurf.

Die __add__ Verfahren auf der anderen Seite, durch list_concat in C dargestellt wird, dauert nur list als Eingabe, wahrscheinlich für Effizienz willen; Es kann direkt über das interne C-Array laufen und Objekte in die neue Liste kopieren.

Abschließend der Grund __iadd__ akzeptiert jede Sequenz, weil, wenn PEP 203 (die Augmented hinzufügen Vorschlag) umgesetzt wurde, für Listen es am einfachsten, die .extend() Methode war einfach wiederzuverwenden.

+0

Danke, Martijn, das ist die Antwort, nach der ich gesucht habe. – alexvassel

9

Wenn a eine Liste, a + x funktioniert nur, wenn x ist auch die Liste, während a += x Arbeiten für jede iterable x.

Nachfolgend könnte es helfen, zu verstehen:

In [4]: a = [] 

In [5]: a += "abc" 

In [6]: a 
Out[6]: ['a', 'b', 'c'] 

Der Schlüssel ist, dass "a" und "abc" iterable sind, das ist, was auf der rechten Seite von += ihre Verwendung ermöglicht.

Dies funktioniert nicht für +, da für Letzteres beide Operanden vom gleichen Typ sind (siehe manual).

die gleiche Sache schreiben + verwenden, müssen Sie die iterable erweitern:

In [7]: a = [] 

In [8]: a = a + list("abc") 

In [9]: a 
Out[9]: ['a', 'b', 'c'] 

Mit anderen Worten, += ist allgemeiner als + wenn auf Listen angewendet.

+0

Die Frage ist die * Differenz * zwischen 'lst + = iterable' und' lst + iterable'. –

+0

Es erklärt nicht, warum Sie eine Liste und ein iterable obwohl nicht verketten können. –

+0

@MartijnPieters: Sicher. Siehe die letzte Antwort. – NPE