Ein häufiges Antimuster in Python besteht darin, eine Folge von Zeichenfolgen +
in einer Schleife zu verketten . Dies ist schlecht, da der Python-Interpreter für jede Iteration ein neues Zeichenfolgenobjekt erstellen muss und dies quadratische Zeit in Anspruch nimmt. (Neuere Versionen von CPython können dies anscheinend in einigen Fällen optimieren, andere Implementierungen jedoch nicht. Daher werden Programmierer davon abgehalten, sich darauf zu verlassen.) Dies ''.join
ist der richtige Weg.
Allerdings habe ich gehört , dass es gesagt ( hier auf Stack - Überlauf einschließlich ) , dass Sie sollten nie, nie verwenden +
für String - Verkettung, sondern immer verwenden ''.join
oder eine Format - String. Ich verstehe nicht, warum dies der Fall ist, wenn Sie nur zwei Zeichenfolgen verketten. Wenn mein Verständnis korrekt ist, sollte es keine quadratische Zeit dauern, und ich denke, es a + b
ist sauberer und lesbarer als entweder ''.join((a, b))
oder '%s%s' % (a, b)
.
Ist es eine gute Praxis, +
zwei Zeichenfolgen zu verketten? Oder gibt es ein Problem, das mir nicht bekannt ist?
+
es schneller oder langsamer ist? Und warum?In [2]: %timeit "a"*80 + "b"*80
1000000 loops, best of 3: 356 ns per loop
In [3]: %timeit "%s%s" % ("a"*80, "b"*80)
1000000 loops, best of 3: 907 ns per loop
In [3]: %timeit "%s%s" % (a, b) 1000000 loops, best of 3: 590 ns per loop
In [4]: %timeit a + b 10000000 loops, best of 3: 147 ns per loop
__str__
. Siehe meine Antwort für Beispiele.Antworten:
Es ist nichts Falsches daran, zwei Zeichenfolgen mit zu verketten
+
. In der Tat ist es leichter zu lesen als''.join([a, b])
.Sie haben jedoch Recht, dass das Verketten von mehr als 2 Zeichenfolgen mit
+
eine O (n ^ 2) -Operation ist (im Vergleich zu O (n) fürjoin
) und somit ineffizient wird. Dies hat jedoch nichts mit der Verwendung einer Schleife zu tun. Geradea + b + c + ...
ist O (n ^ 2), der Grund dafür ist, dass jede Verkettung eine neue Zeichenfolge erzeugt.CPython2.4 und höher versuchen dies zu mildern, es ist jedoch weiterhin ratsam, es zu verwenden,
join
wenn mehr als 2 Zeichenfolgen verkettet werden.quelle
.join
eine iterable, also beide.join([a,b])
und.join((a,b))
sind gültig.+
oder+=
in der akzeptierten Antwort (ab 2013) bei stackoverflow.com/a/12171382/378826 (von Lennart Regebro) auch für CPython 2.3+ und nur wählt den „append / join“ -Muster , wenn dies deutlicher macht die Idee für die vorliegende Problemlösung.Der Plus-Operator ist eine perfekte Lösung, um zwei Python-Zeichenfolgen zu verketten . Wenn Sie jedoch immer mehr als zwei Zeichenfolgen hinzufügen (n> 25), möchten Sie möglicherweise etwas anderes denken.
''.join([a, b, c])
Trick ist eine Leistungsoptimierung.quelle
append()
Strings dynamisch zu generieren und zu einer Liste hinzuzufügen .n > 25
. Menschen brauchen Referenzpunkte, um irgendwo anzufangen.Die Annahme, dass man niemals + für die Verkettung von Zeichenfolgen verwenden sollte, sondern immer '' .join verwenden kann, kann ein Mythos sein. Es ist wahr, dass durch die Verwendung
+
unnötige temporäre Kopien eines unveränderlichen Zeichenfolgenobjekts erstellt werden, aber die andere nicht oft zitierte Tatsache ist, dass das Aufrufenjoin
einer Schleife im Allgemeinen den Overhead von erhöhen würdefunction call
. Nehmen wir Ihr Beispiel.Erstellen Sie zwei Listen, eine aus der verknüpften SO-Frage und eine größere fabrizierte
Lassen Sie uns zwei Funktionen erstellen
UseJoin
undUsePlus
die jeweiligenjoin
und+
Funktionen verwenden.Lassen Sie uns mit der ersten Liste timeit ausführen
Sie haben fast die gleiche Laufzeit.
Verwenden wir cProfile
Und es sieht so aus, als würde die Verwendung von Join zu unnötigen Funktionsaufrufen führen, die den Overhead erhöhen könnten.
Kommen wir nun auf die Frage zurück. Sollte man in allen Fällen von der Verwendung von
+
overjoin
abraten?Ich glaube nein, Dinge sollten berücksichtigt werden
Und natürlich ist eine vorzeitige Optimierung in einer Entwicklung böse.
quelle
join
innerhalb der Schleife selbst zu verwenden, sondern die Schleife würde eine Sequenz erzeugen, die zum Verbinden übergeben würde.Bei der Arbeit mit mehreren Personen ist es manchmal schwierig, genau zu wissen, was passiert. Die Verwendung einer Formatzeichenfolge anstelle einer Verkettung kann eine bestimmte Störung vermeiden, die uns unzählige Male passiert ist:
Angenommen, eine Funktion erfordert ein Argument, und Sie schreiben es in der Erwartung, eine Zeichenfolge zu erhalten:
Daher kann diese Funktion im gesamten Code ziemlich häufig verwendet werden. Ihre Mitarbeiter wissen möglicherweise genau, was sie tun, sind jedoch nicht unbedingt auf dem neuesten Stand der Interna und wissen möglicherweise nicht, dass die Funktion eine Zeichenfolge erwartet. Und so können sie am Ende damit enden:
Es wäre kein Problem, wenn Sie nur eine Formatzeichenfolge verwenden würden:
Gleiches gilt für alle Arten von Objekten, die definieren
__str__
und die ebenfalls übergeben werden können:Also ja: Wenn Sie eine Formatzeichenfolge verwenden können, tun Sie dies und nutzen Sie das, was Python zu bieten hat.
quelle
+
.zeta = u"a\xac\u1234\u20ac\U00008000"
- Sie müssten also verwenden,print 'bar: ' + unicode(zeta)
um sicherzustellen, dass kein Fehler auftritt.%s
macht es richtig, ohne darüber nachdenken zu müssen, und ist viel kürzer"bar: %s"
könnte übersetzt werden"zrb: %s br"
in einer anderen Sprache. Die%s
Version wird nur funktionieren, aber die String-Concat-Version würde ein Chaos werden, um alle Fälle zu behandeln, und Ihre Übersetzer hätten jetzt zwei separate Übersetzungen zudef
.Ich habe einen kurzen Test gemacht:
und zeitlich festgelegt:
Es gibt anscheinend eine Optimierung für den
a = a + b
Fall. Es zeigt keine O (n ^ 2) -Zeit, wie man vermuten könnte.Zumindest in Bezug auf die Leistung ist die Verwendung
+
in Ordnung.quelle
Laut Python-Dokumenten erhalten Sie mit str.join () eine konsistente Leistung für verschiedene Implementierungen von Python. Obwohl CPython das quadratische Verhalten von s = s + t optimiert, ist dies bei anderen Python-Implementierungen möglicherweise nicht der Fall.
Sequenztypen in Python-Dokumenten (siehe Fußnote [6])
quelle
Ich benutze das Folgende mit Python 3.8
quelle
'' .join ([a, b]) ist eine bessere Lösung als + .
Weil Code so geschrieben werden sollte, dass andere Implementierungen von Python (PyPy, Jython, IronPython, Cython, Psyco usw.) nicht benachteiligt werden.
Form a + = b oder a = a + b ist selbst in CPython fragil und in Implementierungen ohne Refcounting überhaupt nicht vorhanden (Referenzzählung ist eine Technik zum Speichern der Anzahl von Referenzen, Zeigern oder Handles auf a Ressource wie ein Objekt, ein Speicherblock, Speicherplatz oder eine andere Ressource )
https://www.python.org/dev/peps/pep-0008/#programming-recommendations
quelle
a += b
funktioniert in allen Implementierungen von Python, es ist nur so, dass es bei einigen von ihnen quadratische Zeit dauert, wenn es in einer Schleife ausgeführt wird ; Die Frage betraf die Verkettung von Zeichenfolgen außerhalb einer Schleife.