fstrings.wtf
(fstrings.wtf)- fstrings.wtf ist ein Online-Quiz, mit dem sich das Verständnis der f-String-Funktion von Python überprüfen lässt
- Es besteht aus Fragen, die die verschiedenen Verhaltensweisen und Ausnahmefälle von f-Strings in der aktuellen Version Python 3.13 testen
- Nutzer können sofort mit dem Quiz beginnen, ohne einen zusätzlichen Prozess durchlaufen zu müssen
- So lassen sich f-String-bezogene Tricks oder Fehlverhalten, denen man in der Praxis häufig begegnet, vorab kennenlernen
1 Kommentare
Hacker-News-Kommentare
String-Interpolation ist wie Typinferenz: Wenn man sich einmal daran gewöhnt hat, fühlt es sich sehr unkomfortabel an, wenn sie fehlt. Wenn man nach und nach mehr hinzufügt, scheint es immer besser zu werden, aber irgendwann merkt man, dass der Code schwer lesbar geworden ist. Generell will man in der Informatik zu jeder Funktionalität gern noch mehr hinzufügen, aber mathematisch ist das manchmal schwierig. Hier sollte man sowohl gar nichts als auch zu viel vermeiden. Python und C# haben sich dafür entschieden, es dem Geschmack der Nutzer zu überlassen. Man kann komplexe Interpolationsstrings über 16 Seiten schreiben, aber die Kollegen könnten das hassen, und im Code-Review fällt es womöglich durch. C++ 23 verfolgt den Stil, Interpolation von Anfang an zu verbieten. Rust hat eine sehr eingeschränkte Option gewählt, die nur die Interpolation von Bezeichnern erlaubt; manchen ist das zu wenig, anderen schon zu viel.
Ich denke, das Java-String-Template-Team hat einen ähnlichen Prozess durchlaufen. Oberflächlich wirkte es wie ein ziemlich cooles System, aber als man es tatsächlich verwenden wollte, fühlte sich die Richtung unmöglich an, sodass es am Ende komplett entfernt wurde. Wenn man den Bedarf an Interpolation und den bisherigen Aufwand bedenkt, ist das eine ziemlich interessante Entscheidung. Man kam offenbar zu dem Schluss, dass es kein Zurück mehr gäbe, und ging deshalb zum Ausgangspunkt zurück.
Reinheit und Pragmatismus stehen im Widerspruch zueinander, und jede Sprache findet dafür einen anderen Gleichgewichtspunkt. Da es keine festgelegte richtige Antwort gibt, behaupten Entwickler immer wieder, dass jeweils ihr eigener Maßstab der richtige sei.
Jedes Mal, wenn ich in C# Zahlen oder Datumswerte formatieren muss, schaue ich zuerst in die Dokumentation. Diese Mini-Sprache ist so unerquicklich, dass ich sie mir gar nicht erst merken will.
Es war nicht schwer, Interpolation sinnvoll zu kontrollieren, ohne komplizierte Beispiele nachzubauen. Ich habe nie die Notwendigkeit gespürt, f-strings in f-strings zu verschachteln, und der einzige Format-Specifier, den ich regelmäßig verwende, ist
:02x.Ich halte Rusts eingeschränkte Art der Interpolation überhaupt nicht für eine Lösung. Da sie nur in bestimmten Situationen funktioniert, muss man bei Refactorings ständig daran denken, und es entsteht unnötige Nacharbeit. Zumindest Feldzugriffe sollten erlaubt sein. In Python gibt es zwar seltsame Fälle wie im Beispiel, aber normale Nutzer kümmern sich nicht darum und verwenden f-strings einfach gerne.
Einige Tipps, die etwa auf fstring.help erklärt werden — zentrierte Ausrichtung, 0x/0b/0o-Präfixe, ASCII-Darstellung usw. — habe ich erst kürzlich gelernt. Ich hatte mich auch für das Problem verschachtelter f-strings interessiert; bis 3.11 ging das, wenn man nur andere Anführungszeichen verwendete. Soweit ich weiß, wurden in 3.12 mehrere Einschränkungen bereinigt. Dank f-strings ist vieles bequemer, aber dass man zwischen altem
%-Formatting,.format()und der neuen Variante mit ihren feinen Unterschieden ständig hin- und herwechseln muss, ist lästiger als gedacht, und es gibt oft unvermeidbare Situationen dafür. Die Benutzbarkeit hat sich verbessert, aber es ist immer noch schade, wenn man alte Wege verwenden muss.In der offiziellen Dokumentation kann man nachlesen, dass das in 3.12 bereinigt wurde.
Gelegentlich sehe ich, wie Kollegen oder eine AI bei Logger-Aufrufen f-strings verwenden, obwohl der Logger doch absichtlich lazy interpolation implementiert hat. Deshalb wundert es mich, dass man diese gute Funktion freiwillig aufgibt.
Ich halte verschachtelte f-strings für ein Trickproblem. Ich wusste, dass hinzugekommen ist, dass man sie mit demselben Stil von Anführungszeichen verschachteln kann, aber ich wusste nicht, in welcher Version. Ich verwende immer noch den Trick
f'{f"{}"}', weil ich meinen Code auch für etwas ältere Python-Versionen unterstützen möchte.Ich habe gerade erst erfahren, dass man in f-strings mit dem Gleichheitszeichen (
=) Ausdruck und Wert zusammen ausgeben kann.Ich finde, die Python-Release-Notes sind wirklich lesenswert. Es gibt immer wieder positive Überraschungen. Die Gleichheitszeichen-Funktion wurde in Python 3.8 hinzugefügt passender Link.
Schade, dass für Funktions-Keyword-Argumente kein ähnliches PEP angenommen wurde. Statt
foo(bar=bar)wäre eine Form wiefoo(bar=)beim Debugging effizienter gewesen, weil dann auch der Unterschied zu Fällen, in denen man nicht bloß ein Argument durchreicht, leichter sichtbar wäre.Ich denke, das ist eine Funktion, die im Verhältnis zu ihrer Überraschungswirkung nicht genug Wert liefert. Es ist gut möglich, dass sie sich unerwartet verhält, und ich habe Sorge, dass sie eine Fehlerquelle wird. Eine Standardfunktion, die nur einen Teil von
locals()ausgibt, wäre vielleicht besser.Das ist ein Muster, das für Debug-Ausgaben extrem häufig verwendet wird. In C++ habe ich mir angewöhnt, einen Ausdruck in Anführungszeichen zu setzen und einen einfach so zu schreiben. Es ist leicht verständlich und angenehm, weil man nicht groß nachdenken muss.
Beim Debugging mit
print(f)ist das wirklich nützlich.Anders als die URL vermuten lässt, gibt es in der Praxis kaum Fragen auf wirklichem WTF-Niveau. Ein paar Dinge wie Frage 20 und 21 sind allerdings wirklich überraschend.
Ich finde den walrus operator so nützlich, dass ich ihn nie wieder aufgeben möchte. Bei Pattern Matching und Verzweigungen mit mehreren Fällen wird der Code dadurch viel sauberer. Ich verwende ihn nicht oft, aber in genau passenden Situationen ist er sehr wirkungsvoll.
Das liegt nicht am walrus operator, sondern an der Funktionsweise von
pythonstring.format; siehe zugehörige Dokumentation.Ich habe Python nie wirklich intensiv vor und nach der Einführung von f-strings verwendet, aber ich habe fast alle Syntaxregeln richtig hinbekommen und eher nur ein paar Fehler beim Rückgabewert gemacht. Vielleicht sind f-strings selbst der am wenigsten WTFige Teil von Python.
Beim Erstellen einer f-string-ähnlichen Bibliothek für Lua habe ich ziemlich viel Syntax gelernt, aber
f"{...}"und den walrus operator hatte ich nicht erwartet. Trotzdem ist das weit entfernt von der Art von Merkwürdigkeit aus Wat. Die zugehörige Bibliothek gibt es hier.Ich finde nicht, dass hier etwas besonders WTF-artig ist. Ein großer Teil davon betrifft eher die Syntax der
str.format()-Mini-Sprache als f-strings selbst.Die Funktionalität ist zu umfangreich geworden und scheint einen kritischen Punkt überschritten zu haben. Kein einzelner Entwickler muss alles kennen, und es ist ineffizient, dass man jedes Mal die Dokumentation nachschlagen muss, wenn man es wirklich braucht. Weil man es selten verwendet, vergisst man die Syntax wieder, und dieselbe Funktion selbst zu implementieren ist oft viel schneller; außerdem lässt sie sich dann für Kollegen leichter anpassen. Left Padding? Dafür reicht eine Funktion mit zwei Zeilen. Bevor ich darüber rätsle, ob in der Formatierungssyntax
nvor<kommt oder umgekehrt, implementiere ich es lieber ad hoc direkt selbst.Dinge wie Left Padding kann man auch mit der Methode
string.formatverwenden, und diese Variante gibt es schon seit Python 2.6 (veröffentlicht 2008); siehe zugehörige Dokumentation. Mir bleibt die Format-Syntax eher gut im Kopf, deshalb nutze ich sie gern. Außerdem ist das Formatting für Anpassungen erweiterbar.Ich hätte gern einen Mittelweg. Am angenehmsten wären
pad_left-/pad_right-Funktionen, bei denen man das Füllzeichen auch direkt als Keyword-Argument angeben kann. So etwas braucht man im Alltag immer wieder, deshalb wäre es schön, wenn es das in der Standardbibliothek gäbe. Wenn eine Sprachbibliothek so etwas nicht hat, endet es später damit, dass in jedem Projekt minderwertige Eigenimplementierungen herumliegen, wie in JavaScript. In meinem Projekt würde ich Python-Formatierungen wie^oder<>wohl nie brauchen, aber in Software, bei der die Ausgabe in Monospace wichtig ist, können solche Funktionen im Gegenteil sehr wichtig sein.Es gibt Fälle, in denen man seltsame Funktionen oder Workarounds in einer Codebasis immer wieder häufig verwendet. Oft baut man es einmal und kopiert es dann weiter, um es ständig wiederzuverwenden.
Wenn diese Syntax JavaScript gewesen wäre, hätten die meisten wohl über unintuive Syntax und seltsame Funktionen gejammert.
Ich denke, die eigentliche Pointe dieses Quiz ist, dass Python fast so viele footguns hat wie JavaScript. Vielleicht liegt das daran, dass es zu JS häufig solche „WTF“-Posts gibt.
Auch wenn man die kleinen Tricks weglässt, ist JavaScript meiner Meinung nach mit großem Abstand der König unintuitiver Syntax. Die f-string-Elemente von Python sind zwar auch eigenartig, tauchen aber nur in bestimmten Situationen auf, und in JS wartet man schon auf die Installation von Abhängigkeiten, bevor man überhaupt zwei Arrays vergleichen kann.
Ich wollte zu JavaScript-Template-Literals etwas fragen. Anders als in Python scheint man in JS nicht mehrfach dynamisch Werte in etwas wie
let template = 'hello ${name}';und danntemplate.format({ name: 'joe' })einsetzen zu können. Deshalb blieb mir nichts anderes übrig, als es selbst zu implementieren. Ich habe mir auch Tagged Templates angesehen, aber es war schwierig, das Template selbst wiederzuverwenden. Das Jammern über JS-Syntax oder seltsame Features kann ich jedenfalls sehr gut nachvollziehen.Wenn es Perl gewesen wäre, hätte es dafür vermutlich eher Lob gehagelt.
Ich nutze pyformat.info als Referenz; es ist zwar nicht extrem detailliert, deckt aber die meisten vernünftigen Beispiele ab.