Es ist keine eingebaut reverse Funktion für Pythons str Objekt. Wie setzt man diese Methode am besten um?
Wenn Sie eine sehr knappe Antwort geben, erläutern Sie bitte deren Effizienz. Ob zum Beispiel die str Objekt wird in ein anderes Objekt umgewandelt usw.
Paolo Bergantino
Slicen verwenden:
>>> 'hello world'[::-1]
'dlrow olleh'
Die Slice-Notation nimmt die Form an [start:stop:step]. In diesem Fall verzichten wir auf die start und stop Positionen, da wir die ganze Zeichenfolge wollen. Wir benützen auch step = -1was bedeutet, “wiederholt um 1 Zeichen von rechts nach links gehen”.
Diese Lösung (und die meisten anderen Antworten) funktioniert nicht für den gesamten Unicode, selbst wenn sie auf Python-Unicode-Strings angewendet wird. Zum Beispiel, "🇬🇧"[::-1] Erträge "🇧🇬". Die richtige Lösung ist reversed_string = "".join(list(grapheme.graphemes(input_string))[::-1]). Siehe Martins Antwort unten.
– Amaurea
5. April 2021 um 2:00 Uhr
Alex Martell
@Paolo s[::-1] ist am schnellsten; ein langsamerer Ansatz (vielleicht lesbarer, aber darüber lässt sich streiten) ist ''.join(reversed(s)).
Dies ist etwa 3 mal langsamer.
– man selbst
6. Oktober 2017 um 15:09 Uhr
Und ein kurzer Kommentar, um zu sagen, was es tut, wird es besser erklären, als diese langsamere Version zu verwenden!
– Tom Burrows
2. November 2017 um 22:04 Uhr
es ist langsamer, weil joinhat um die Liste trotzdem aufzubauen, um die Größe zu bekommen. ''.join(list(reversed(s))) kann etwas schneller sein.
– Jean-Francois Fabre ♦
11. Dezember 2017 um 21:34 Uhr
Hast du irgendwelche Infos warum [::-1] ist am schnellsten? Ich möchte tiefer eintauchen.
– Gerber
30. Oktober 2019 um 17:03 Uhr
@Gerber [::-1] ist am schnellsten, weil es keine externen Funktionen aufruft, sondern Slicing verwendet, das in Python hochoptimiert ist. ”.join(list(reversed(s))) macht 3 Funktionsaufrufe.
– hd1
27. April 2020 um 13:51 Uhr
Russland muss Putin entfernen
Was ist der beste Weg, um eine Umkehrfunktion für Zeichenfolgen zu implementieren?
Meine eigene Erfahrung mit dieser Frage ist akademisch. Wenn Sie jedoch ein Profi sind, der nach der schnellen Antwort sucht, verwenden Sie ein Stück, das schrittweise vorbeikommt -1:
>>> 'a string'[::-1]
'gnirts a'
oder lesbarer (aber langsamer aufgrund der Suche nach Methodennamen und der Tatsache, dass Join eine Liste bildet, wenn ein Iterator angegeben wird), str.join:
>>> ''.join(reversed('a string'))
'gnirts a'
oder fügen Sie den Slice aus Gründen der Lesbarkeit und Wiederverwendbarkeit in eine Funktion ein
Wenn Sie an der akademischen Ausstellung interessiert sind, lesen Sie bitte weiter.
Es gibt keine eingebaute Reverse-Funktion im str-Objekt von Python.
Hier sind ein paar Dinge über Pythons Strings, die Sie wissen sollten:
In Python, Zeichenfolgen sind unveränderlich. Durch das Ändern einer Zeichenfolge wird die Zeichenfolge nicht geändert. Es schafft ein neues.
Saiten sind schneidbar. Durch das Schneiden einer Zeichenfolge erhalten Sie eine neue Zeichenfolge von einem Punkt in der Zeichenfolge rückwärts oder vorwärts zu einem anderen Punkt in bestimmten Schritten. Sie nehmen Slice-Notation oder ein Slice-Objekt in einem Index:
string[subscript]
Der Index erstellt einen Slice, indem er einen Doppelpunkt in die geschweiften Klammern einfügt:
string[start:stop:step]
Um ein Slice außerhalb der geschweiften Klammern zu erstellen, müssen Sie ein Slice-Objekt erstellen:
Während ''.join(reversed('foo')) lesbar ist, erfordert es den Aufruf einer String-Methode, str.join, auf einer anderen aufgerufenen Funktion, die relativ langsam sein kann. Setzen wir das in eine Funktion – wir kommen darauf zurück:
Viel schneller ist die Verwendung eines umgekehrten Slice:
'foo'[::-1]
Aber wie können wir dies für jemanden, der mit Slices oder der Absicht des ursprünglichen Autors weniger vertraut ist, lesbarer und verständlicher machen? Lassen Sie uns ein Slice-Objekt außerhalb der tiefgestellten Notation erstellen, ihm einen beschreibenden Namen geben und es an die tiefgestellte Notation übergeben.
Wenn Sie einen Lehrer haben, möchte er wahrscheinlich, dass Sie mit einer leeren Saite beginnen und eine neue Saite aus der alten aufbauen. Sie können dies mit reiner Syntax und Literalen mithilfe einer While-Schleife tun:
def reverse_a_string_slowly(a_string):
new_string = ''
index = len(a_string)
while index:
index -= 1 # index = index - 1
new_string += a_string[index] # new_string = new_string + character
return new_string
Das ist theoretisch schlecht, denn denken Sie daran, Zeichenfolgen sind unveränderlich – also jedes Mal, wenn es so aussieht, als würden Sie ein Zeichen an Ihr anhängen new_string, es erstellt theoretisch jedes Mal eine neue Zeichenfolge! CPython weiß jedoch, wie dies in bestimmten Fällen optimiert werden kann, von denen dieser triviale Fall einer ist.
Beste Übung
Theoretisch besser ist es, Ihre Teilstrings in einer Liste zu sammeln und später zusammenzufügen:
def reverse_a_string_more_slowly(a_string):
new_strings = []
index = len(a_string)
while index:
index -= 1
new_strings.append(a_string[index])
return ''.join(new_strings)
Wie wir jedoch in den folgenden Timings für CPython sehen werden, dauert dies tatsächlich länger, da CPython die Zeichenfolgenverkettung optimieren kann.
CPython optimiert die Zeichenfolgenverkettung, während andere Implementierungen nicht dürfen:
… verlassen Sie sich nicht auf CPythons effiziente Implementierung der direkten Zeichenfolgenverkettung für Anweisungen in der Form a += b oder a = a + b . Diese Optimierung ist selbst in CPython anfällig (sie funktioniert nur für einige Typen) und ist in Implementierungen, die kein Refcounting verwenden, überhaupt nicht vorhanden. In leistungsempfindlichen Teilen der Bibliothek sollte stattdessen die Form „.join()“ verwendet werden. Dadurch wird sichergestellt, dass die Verkettung über verschiedene Implementierungen hinweg in linearer Zeit erfolgt.
Ich liebe diese Antwort, Erklärungen zu Optimierungen, Lesbarkeit vs. Optimierung, Tipps zu den Wünschen des Lehrers. Ich bin mir nicht sicher über den Best-Practice-Abschnitt mit dem while und den Index dekrementieren, obwohl dies vielleicht weniger lesbar ist: for i in range(len(a_string)-1, -1, -1): . Am meisten finde ich es toll, dass die von Ihnen gewählte Beispielzeichenfolge der einzige Fall ist, in dem Sie sie niemals umkehren müssten und nicht sagen könnten, ob Sie es getan hätten 🙂
Diese Antwort wird bereitgestellt, um das folgende Anliegen von @odigity anzusprechen:
Wow. Zuerst war ich entsetzt über die von Paolo vorgeschlagene Lösung, aber das trat in den Hintergrund des Entsetzens, das ich empfand, als ich den ersten Kommentar las: „Das ist sehr pythonisch. Gute Arbeit!“ Ich bin so beunruhigt, dass eine so kluge Community denkt, dass es eine gute Idee ist, solch kryptische Methoden für etwas so Grundlegendes zu verwenden. Warum liegt es nicht einfach an reverse()?
Problem
Kontext
Python 2.x
Python 3.x
Szenario:
Der Entwickler möchte eine Zeichenfolge umwandeln
Die Transformation erfolgt in umgekehrter Reihenfolge aller Zeichen
Der Entwickler erwartet möglicherweise etwas wie string.reverse()
Die native idiomatische (alias „pythonische“) Lösung ist möglicherweise für neuere Entwickler nicht lesbar
Entwickler könnten versucht sein, ihre eigene Version von zu implementieren string.reverse() Slice-Notation zu vermeiden.
Die Ausgabe der Slice-Notation kann in einigen Fällen kontraintuitiv sein:
siehe zB Beispiel02
print 'coup_ate_grouping'[-4:] ## => 'ping'
verglichen mit
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
verglichen mit
print 'coup_ate_grouping'[-1] ## => 'g'
die unterschiedlichen Ergebnisse der Indizierung auf [-1] kann einige Entwickler abschrecken
Begründung
Python hat einen besonderen Umstand zu beachten: ein String ist ein wiederholbar Art.
Ein Grund für den Ausschluss von a string.reverse() Die Methode besteht darin, Python-Entwicklern einen Anreiz zu geben, die Macht dieser besonderen Umstände zu nutzen.
Vereinfacht ausgedrückt bedeutet dies einfach, dass jedes einzelne Zeichen in einer Zeichenfolge einfach als Teil einer sequentiellen Anordnung von Elementen bearbeitet werden kann, genau wie Arrays in anderen Programmiersprachen.
Um zu verstehen, wie dies funktioniert, kann die Überprüfung von example02 einen guten Überblick geben.
Die kognitive Belastung in Verbindung mit dem Verständnis, wie die Slice-Notation in Python funktioniert, kann für einige Anwender und Entwickler, die nicht viel Zeit in das Erlernen der Sprache investieren möchten, tatsächlich zu viel sein.
Sobald die Grundprinzipien verstanden sind, kann die Leistungsfähigkeit dieses Ansatzes gegenüber festen String-Manipulationsmethoden jedoch recht günstig sein.
Für diejenigen, die anderer Meinung sind, gibt es alternative Ansätze wie Lambda-Funktionen, Iteratoren oder einfache einmalige Funktionsdeklarationen.
Auf Wunsch kann ein Entwickler seine eigene string.reverse()-Methode implementieren, es ist jedoch gut, die Gründe für diesen Aspekt von Python zu verstehen.
Siehe auch
alternativer einfacher Ansatz
alternativer einfacher Ansatz
alternative Erklärung der Slice-Notation
Martin Thomas
Diese Antwort ist etwas länger und enthält 3 Abschnitte: Benchmarks bestehender Lösungen, warum die meisten Lösungen hier falsch sind, meine Lösung.
Die vorhandenen Antworten sind nur richtig, wenn Unicode-Modifikatoren / Graphem-Cluster ignoriert werden. Darauf gehe ich später ein, aber werfen Sie zunächst einen Blick auf die Geschwindigkeit einiger Umkehralgorithmen:
HINWEIS: Ich habe, was ich angerufen habe list_comprehension aufgerufen werden soll slicing
Sie können sehen, dass die Zeit für das Listenverständnis (reversed = string[::-1]) ist in allen Fällen bei weitem am niedrigsten (auch nachdem ich meinen Tippfehler behoben habe).
Saitenumkehrung
Wenn Sie wirklich eine Zeichenfolge im gesunden Menschenverstand umkehren möchten, ist es viel komplizierter. Nehmen Sie zum Beispiel die folgende Zeichenfolge (brauner Finger, der nach links zeigt, gelber Finger nach oben). Das sind zwei Grapheme, aber 3 Unicode-Codepunkte. Der zusätzliche ist ein Hautmodifikator.
example = "👈🏾👆"
Aber wenn Sie es mit einer der angegebenen Methoden umkehren, erhalten Sie brauner Finger nach oben, gelber Finger nach links. Der Grund dafür ist, dass der Farbmodifikator “Braun” immer noch in der Mitte ist und auf alles angewendet wird, was davor ist. Also haben wir
Vielen Dank für das Zeigen der richtigen Graphem-bewussten String-Umkehrung. Für fast jeden realistischen Zweck sind alle anderen Antworten hier falsch. Schade, dass Sie weniger als 1 % der Stimmen für die beliebteste Antwort haben.
– Amaurea
5. April 2021 um 1:50 Uhr
Es ist jedoch ein bisschen unglücklich, dass Ihre Lösung inmitten vieler Benchmarking-Sachen halb versteckt ist. Ich würde es viel früher und prominenter setzen und vielleicht explizit zeigen, wie die einfachen Lösungen der anderen schief gehen (Sie beschreiben es, aber zeigen es nicht). Flaggen-Emojis sind ebenfalls gute Beispiele dafür.
– Amaurea
5. April 2021 um 1:52 Uhr
Gut zu sehen, dass es sich lohnt, nicht nur die Antworten am Anfang zu lesen. Übrigens: Wäre es nicht besser, die Statistiken (einschließlich Ihrer graphemfähigen Version) am Ende zu bringen?
– Wolf
11. September 2022 um 17:38 Uhr
Warum tut Ihr list_comprehension Funktion enthält keine Liste Comprehensions?
– Kelwood
11. Dezember 2022 um 7:47 Uhr
@khelwood Du hast Recht, “Slicing” wäre ein besserer Name gewesen. Ich bin jetzt allerdings zu faul, die ganze Grafik anzupassen … vielleicht wäre ein “3.11”-Update aber interessant
– Martin Thoma
12. Dezember 2022 um 13:23 Uhr
1. Verwendung der Slice-Notation
def rev_string(s):
return s[::-1]
2. Verwendung der Funktion reversed()
def rev_string(s):
return ''.join(reversed(s))
3. Verwendung von Rekursion
def rev_string(s):
if len(s) == 1:
return s
return s[-1] + rev_string(s[:-1])
Vielen Dank für das Zeigen der richtigen Graphem-bewussten String-Umkehrung. Für fast jeden realistischen Zweck sind alle anderen Antworten hier falsch. Schade, dass Sie weniger als 1 % der Stimmen für die beliebteste Antwort haben.
– Amaurea
5. April 2021 um 1:50 Uhr
Es ist jedoch ein bisschen unglücklich, dass Ihre Lösung inmitten vieler Benchmarking-Sachen halb versteckt ist. Ich würde es viel früher und prominenter setzen und vielleicht explizit zeigen, wie die einfachen Lösungen der anderen schief gehen (Sie beschreiben es, aber zeigen es nicht). Flaggen-Emojis sind ebenfalls gute Beispiele dafür.
– Amaurea
5. April 2021 um 1:52 Uhr
Gut zu sehen, dass es sich lohnt, nicht nur die Antworten am Anfang zu lesen. Übrigens: Wäre es nicht besser, die Statistiken (einschließlich Ihrer graphemfähigen Version) am Ende zu bringen?
– Wolf
11. September 2022 um 17:38 Uhr
Warum tut Ihr list_comprehension Funktion enthält keine Liste Comprehensions?
– Kelwood
11. Dezember 2022 um 7:47 Uhr
@khelwood Du hast Recht, “Slicing” wäre ein besserer Name gewesen. Ich bin jetzt allerdings zu faul, die ganze Grafik anzupassen … vielleicht wäre ein “3.11”-Update aber interessant