Ich habe gesehen, dass es in Python tatsächlich zwei (vielleicht mehr) Möglichkeiten gibt, Listen zu verketten: Eine Möglichkeit ist die Verwendung der Extend () -Methode:
a = [1, 2]
b = [2, 3]
b.extend(a)
der andere, um den Plus-Operator (+) zu verwenden:
b += a
Jetzt frage ich mich: Welche dieser beiden Optionen ist die "pythonische" Methode zur Listenverkettung und gibt es einen Unterschied zwischen den beiden (ich habe das offizielle Python-Tutorial nachgeschlagen, konnte aber nichts zu diesem Thema finden).
.__iadd__()
/.__add__()
/.__radd__()
versus.extend()
Antworten:
Der einzige Unterschied auf Bytecode-Ebene besteht darin, dass es
.extend
sich um einen Funktionsaufruf handelt, der in Python etwas teurer ist als derINPLACE_ADD
.Es ist wirklich nichts, worüber Sie sich Sorgen machen sollten, es sei denn, Sie führen diese Operation milliardenfach durch. Es ist jedoch wahrscheinlich, dass der Engpass an einem anderen Ort liegen würde.
quelle
.__iadd__()
/.__add__()
/.__radd__()
versus.extend()
Sie können + = nicht für nicht lokale Variablen verwenden (Variablen, die für Funktionen nicht lokal und auch nicht global sind)
Dies liegt daran , dass der Compiler für Extended Case die Variable
l
mithilfe derLOAD_DEREF
Anweisung lädt , für + = jedochLOAD_FAST
- und Sie erhalten*UnboundLocalError: local variable 'l' referenced before assignment*
quelle
Sie können Funktionsaufrufe verketten, aber Sie können + = einen Funktionsaufruf nicht direkt:
quelle
Ich würde sagen, dass es einen Unterschied gibt, wenn es um Numpy geht (ich habe gerade gesehen, dass die Frage nach der Verkettung von zwei Listen und nicht nach Numpy-Array gestellt wird, aber da dies für Anfänger wie mich ein Problem sein könnte, hoffe ich, dass dies jemandem helfen kann die die Lösung für diesen Beitrag suchen), zum Beispiel.
es wird mit Fehler zurückgegeben
ValueError: Operanden konnten nicht zusammen mit Shapes (0,) (4,4,4) gesendet werden.
b.extend(a)
funktioniert perfektquelle
Aus dem CPython 3.5.2-Quellcode : Kein großer Unterschied.
quelle
verlängern () funktioniert mit jedem iterierbaren *, + = funktioniert mit einigen, kann aber funky werden.
Python 3.6
* ist sich ziemlich sicher, dass .extend () mit jedem iterierbaren Element funktioniert, aber bitte kommentieren Sie, wenn ich falsch bin
quelle
list.extend(iterable) Extend the list by appending all the items from the iterable. Equivalent to a[len(a):] = iterable.
Vermutlich habe ich mein eigenes Sternchen beantwortet.+=
Operator mit Objekten unterschiedlichen Typs verwenden (im Gegensatz zu zwei Listen, wie in der Frage), können Sie nicht erwarten, dass Sie eine Verkettung der Objekte erhalten. Und Sie können nicht erwarten, dass einlist
Typ zurückgegeben wird. Schauen Sie sich Ihren Code an, Sie erhalten einennumpy.ndarray
stattlist
.Tatsächlich gibt es Unterschiede zwischen den drei Optionen:
ADD
,INPLACE_ADD
undextend
. Ersteres ist immer langsamer, während die anderen beiden ungefähr gleich sind.Mit diesen Informationen würde ich lieber verwenden
extend
, was schneller ist alsADD
und mir expliziter erscheint, was Sie tun alsINPLACE_ADD
.Versuchen Sie den folgenden Code einige Male (für Python 3):
quelle
ADD
mitINPLACE_ADD
und vergleichenextend()
.ADD
erstellt eine neue Liste und kopiert die Elemente der beiden ursprünglichen Listen in diese. Sicher ist es langsamer als der Inplace-Betrieb vonINPLACE_ADD
undextend()
.Diese Informationen sind zufällig in den Programmier-FAQ vergraben :
Sie können dies auch im CPython-Quellcode selbst sehen: https://github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011
quelle
Nach dem Python für Datenanalyse.
„Beachten Sie, dass die Verkettung von Listen durch Hinzufügen eine vergleichsweise teure Operation ist, da eine neue Liste erstellt und die Objekte kopiert werden müssen. Die Verwendung von "Erweitern" zum Anhängen von Elementen an eine vorhandene Liste, insbesondere wenn Sie eine große Liste erstellen, ist normalerweise vorzuziehen. So also
ist schneller als die verkettete Alternative:
quelle
everything = everything + temp
wird nicht unbedingt auf die gleiche Weise implementiert wieeverything += temp
.everything += temp
ist so implementiert, dasseverything
es nicht kopiert werden muss. Dies macht Ihre Antwort zu einem strittigen Punkt.