Das Erstellen langer Zeichenfolgen in der Python-Programmiersprache kann manchmal zu sehr langsam laufendem Code führen. In diesem Artikel untersuche ich die Rechenleistung verschiedener String-Verkettungsmethoden.
Beachten Sie, dass dieser Artikel auf Python 2.2 basiert. Die Tests würden in einer modernen Version von Python wahrscheinlich etwas anders ablaufen (CPython optimiert normalerweise erfolgreich die Verkettung, aber Sie möchten sich in wichtigen Codes nicht darauf verlassen), und ein Generatorausdruck, bei dem er ein Listenverständnis verwendet, wäre erwägenswert .
Mike Graham
4
Es wäre gut, einige Highlights in diesem Artikel zu erwähnen, zumindest einige der Implementierungen (um Probleme mit der Verbindungsfäule zu vermeiden).
jpmc26
3
Methode 1: resultString + = appendString ist der schnellste nach Tests von @ Antoine-tran unten
Justas
5
Ihr Zitat beantwortet die Frage überhaupt nicht. Bitte fügen Sie die entsprechenden Teile in Ihre Antwort selbst ein, um den neuen Richtlinien zu entsprechen.
Fund Monica Klage
27
Ich habe den Code von Oliver Crow (Link von Andrew Hare) verwendet und ihn ein wenig angepasst, um Python 2.7.3 anzupassen. (mit timeit package). Ich lief auf meinem PC, Lenovo T61, 6 GB RAM, Debian GNU / Linux 6.0.6 (Squeeze).
Es ist ziemlich offensichtlich, dass Python-Leute großartige Arbeit geleistet haben, um die Verkettung von Strings zu optimieren, und wie Hoare sagte: "Vorzeitige Optimierung ist die Wurzel allen Übels" :-)
Es ist keine vorzeitige Optimierung, um fragile, interpretatorabhängige Optimierungen zu vermeiden. Wenn Sie jemals auf PyPy portieren möchten oder das Risiko eingehen, einen der vielen subtilen Fehlerfälle für die Optimierung zu treffen , gehen Sie richtig vor.
Veedrac
1
Es sieht so aus, als ob Methode 1 für den Compiler einfacher zu optimieren ist.
mbomb007
23
Sich auf Compiler-Optimierungen zu verlassen, ist fragil. Den in der akzeptierten Antwort und den von Antoine-tran angegebenen Zahlen verknüpften Benchmarks ist nicht zu trauen. Andrew Hare macht den Fehler, einen Aufruf an reprin seine Methoden aufzunehmen. Das verlangsamt alle Methoden gleichermaßen, verdeckt aber die wirkliche Strafe beim Erstellen des Strings.
Verwenden Sie join. Es ist sehr schnell und robuster.
$ ipython3
Python3.5.1(default,Mar22016,03:38:02)IPython4.1.2--An enhanced InteractivePython.In[1]: values =[str(num)for num in range(int(1e3))]In[2]:%%timeit
...:''.join(values)...:100000 loops, best of 3:7.37µs per loop
In[3]:%%timeit
...: result =''...:for value in values:...: result += value
...:10000 loops, best of 3:82.8µs per loop
In[4]:import io
In[5]:%%timeit
...: writer = io.StringIO()...:for value in values:...: writer.write(value)...: writer.getvalue()...:10000 loops, best of 3:81.8µs per loop
Ja, der reprAufruf dominiert die Laufzeit, aber es besteht keine Notwendigkeit, den Fehler persönlich zu machen.
Alex Reinking
3
@ AlexReinking sorry, nichts persönliches gemeint. Ich bin mir nicht sicher, warum du es für persönlich gehalten hast. Aber wenn es die Verwendung ihrer Namen war, habe ich diese nur verwendet, um auf die Antworten des Benutzers zu verweisen (stimmt mit Benutzernamen überein, nicht sicher, ob es einen besseren Weg gibt).
GrantJ
1
gutes Timing-Beispiel, das
Dateninitialisierungs-
19
Python hat mehrere Dinge, die ähnliche Zwecke erfüllen:
Eine übliche Methode, um große Zeichenfolgen aus Teilen zu erstellen, besteht darin, eine Liste von Zeichenfolgen zu erstellen und diese zu verbinden, wenn Sie fertig sind. Dies ist eine häufig verwendete Python-Sprache.
Um Zeichenfolgen zu erstellen, die Daten mit Formatierung enthalten, müssen Sie die Formatierung separat durchführen.
Zum Einfügen und Löschen auf Zeichenebene würden Sie eine Liste mit Zeichenfolgen der Länge 1 führen. (Um dies aus einer Zeichenfolge zu machen, würden Sie aufrufen list(your_string). Sie können auch eine UserString.MutableStringdafür verwenden.
(c)StringIO.StringIO ist nützlich für Dinge, die sonst eine Datei benötigen würden, aber weniger für die allgemeine Zeichenfolgenerstellung.
Es gibt kein explizites Analogon - ich denke, es wird erwartet, dass Sie Zeichenfolgenverkettungen (wahrscheinlich wie oben beschrieben optimiert) oder Klassen von Drittanbietern (ich bezweifle, dass sie viel effizienter sind) verwenden - Listen in Python sind dynamisch typisiert, sodass sie nicht schnell funktionieren char [] für Puffer, wie ich annehme). Stringbuilder-ähnliche Klassen sind keine vorzeitige Optimierung, da Strings in vielen Sprachen angeboren sind (Unveränderlichkeit) - dies ermöglicht viele Optimierungen (z. B. Verweisen auf denselben Puffer für Slices / Teilzeichenfolgen). Stringbuilder- / Stringbuffer- / Stringstream-ähnliche Klassen arbeiten viel schneller als das Verketten von Strings (wodurch viele kleine temporäre Objekte erzeugt werden, für die noch Zuordnungen und Speicherbereinigung erforderlich sind) und sogar das Formatieren von printf-ähnlichen Tools für das Formatieren von Zeichenfolgen, ohne dass der Aufwand für das Formatieren von Formatierungsmustern ziemlich aufwendig ist viele Formataufrufe.
Wenn Sie hier nach einer schnellen String-Verkettungsmethode in Python suchen, benötigen Sie keine spezielle StringBuilder-Klasse. Einfache Verkettung funktioniert genauso gut ohne den Leistungsverlust in C #.
Antworten:
Es gibt keine Eins-zu-Eins-Korrelation. Einen wirklich guten Artikel finden Sie unter Effiziente String-Verkettung in Python :
quelle
Ich habe den Code von Oliver Crow (Link von Andrew Hare) verwendet und ihn ein wenig angepasst, um Python 2.7.3 anzupassen. (mit timeit package). Ich lief auf meinem PC, Lenovo T61, 6 GB RAM, Debian GNU / Linux 6.0.6 (Squeeze).
Hier ist das Ergebnis für 10.000 Iterationen:
und für 5.000.000 Iterationen (Methode 2 wurde ignoriert, weil sie wie für immer zu langsam lief):
Es ist ziemlich offensichtlich, dass Python-Leute großartige Arbeit geleistet haben, um die Verkettung von Strings zu optimieren, und wie Hoare sagte: "Vorzeitige Optimierung ist die Wurzel allen Übels" :-)
quelle
Sich auf Compiler-Optimierungen zu verlassen, ist fragil. Den in der akzeptierten Antwort und den von Antoine-tran angegebenen Zahlen verknüpften Benchmarks ist nicht zu trauen. Andrew Hare macht den Fehler, einen Aufruf an
repr
in seine Methoden aufzunehmen. Das verlangsamt alle Methoden gleichermaßen, verdeckt aber die wirkliche Strafe beim Erstellen des Strings.Verwenden Sie
join
. Es ist sehr schnell und robuster.quelle
repr
Aufruf dominiert die Laufzeit, aber es besteht keine Notwendigkeit, den Fehler persönlich zu machen.Python hat mehrere Dinge, die ähnliche Zwecke erfüllen:
list(your_string)
. Sie können auch eineUserString.MutableString
dafür verwenden.(c)StringIO.StringIO
ist nützlich für Dinge, die sonst eine Datei benötigen würden, aber weniger für die allgemeine Zeichenfolgenerstellung.quelle
Mit Methode 5 von oben (The Pseudo File) können wir eine sehr gute Leistung und Flexibilität erzielen
jetzt benutze es
quelle
Sie können StringIO oder cStringIO ausprobieren
quelle
Es gibt kein explizites Analogon - ich denke, es wird erwartet, dass Sie Zeichenfolgenverkettungen (wahrscheinlich wie oben beschrieben optimiert) oder Klassen von Drittanbietern (ich bezweifle, dass sie viel effizienter sind) verwenden - Listen in Python sind dynamisch typisiert, sodass sie nicht schnell funktionieren char [] für Puffer, wie ich annehme). Stringbuilder-ähnliche Klassen sind keine vorzeitige Optimierung, da Strings in vielen Sprachen angeboren sind (Unveränderlichkeit) - dies ermöglicht viele Optimierungen (z. B. Verweisen auf denselben Puffer für Slices / Teilzeichenfolgen). Stringbuilder- / Stringbuffer- / Stringstream-ähnliche Klassen arbeiten viel schneller als das Verketten von Strings (wodurch viele kleine temporäre Objekte erzeugt werden, für die noch Zuordnungen und Speicherbereinigung erforderlich sind) und sogar das Formatieren von printf-ähnlichen Tools für das Formatieren von Zeichenfolgen, ohne dass der Aufwand für das Formatieren von Formatierungsmustern ziemlich aufwendig ist viele Formataufrufe.
quelle
Wenn Sie hier nach einer schnellen String-Verkettungsmethode in Python suchen, benötigen Sie keine spezielle StringBuilder-Klasse. Einfache Verkettung funktioniert genauso gut ohne den Leistungsverlust in C #.
Siehe Antoine-trans Antwort für Leistungsergebnisse
quelle