fstrings.wtf
(fstrings.wtf)- fstrings.wtf est un quiz en ligne conçu pour évaluer la compréhension de la fonctionnalité f-string de Python
- Il se compose de questions qui testent les différents comportements des f-strings et leurs cas d’exception dans la dernière version, Python 3.13
- Les utilisateurs peuvent commencer le quiz immédiatement sans aucune étape préalable
- Il permet de découvrir à l’avance des astuces ou des comportements erronés liés aux f-strings que l’on rencontre souvent en pratique
1 commentaires
Avis Hacker News
Comme l’inférence de types, l’interpolation de chaînes devient très inconfortable à ne pas avoir une fois qu’on y est habitué. On a l’impression que plus on en ajoute progressivement, mieux c’est, jusqu’au moment où l’on réalise que le code devient difficile à lire. En général, en informatique, on a tendance à vouloir toujours ajouter des fonctionnalités, mais mathématiquement ce n’est pas toujours simple. Ici, il faut éviter à la fois l’absence totale et l’excès. Python et C# ont choisi de laisser cela aux préférences de l’utilisateur. On peut écrire une chaîne d’interpolation complexe sur 16 pages, mais ses collègues peuvent la détester et elle peut être rejetée en revue de code. C++ 23 adopte au contraire un style qui interdit l’interpolation dès le départ. Rust a choisi une option très restrictive qui n’autorise l’interpolation que pour les identifiants, ce qui pourra paraître insuffisant à certains, et excessif à d’autres
Je pense que l’équipe Java String Template a traversé un processus similaire. Le système paraissait très élégant au premier abord, mais à l’usage ils ont eu le sentiment que cette direction n’était pas viable, et ils l’ont finalement retiré complètement. C’est une décision assez intéressante, vu la demande pour l’interpolation et les efforts déjà investis jusque-là. Ils ont finalement jugé qu’il n’y avait pas de retour possible et sont revenus au point de départ
Pureté et pragmatisme sont en tension, et chaque langage finit par trouver un point d’équilibre différent. Comme il n’existe pas de bonne réponse universelle, les développeurs répètent sans cesse que leur propre critère est le bon
Chaque fois que j’ai besoin de formater des nombres ou des dates en C#, je commence par consulter la documentation. Ce mini-langage est tellement mauvais que j’ai décidé de ne pas l’apprendre par cœur
Il n’était pas difficile de contrôler correctement l’interpolation sans chercher à faire fonctionner des exemples complexes. Je n’ai jamais ressenti le besoin d’imbriquer des f-strings dans des f-strings, et le seul spécificateur de format que j’utilise souvent est
:02xJe ne pense pas du tout que l’interpolation restrictive de Rust soit une solution. Comme elle ne fonctionne que dans certains cas, il faut y penser en permanence lors des refactorings, et cela entraîne beaucoup de retouches inutiles. À minima, il faudrait autoriser l’accès aux champs. En revanche, en Python, même s’il existe des cas étranges comme dans l’exemple, les utilisateurs en pratique n’y pensent pas et utilisent simplement les f-strings avec plaisir
J’ai récemment découvert quelques astuces expliquées sur fstring.help, comme le centrage, les préfixes 0x/0b/0o, l’affichage ASCII, etc. Je m’intéressais aussi au problème des f-strings imbriquées, et jusqu’à la 3.11 c’était possible à condition de changer les guillemets. Je crois savoir qu’en 3.12 plusieurs restrictions ont été levées. Les f-strings sont pratiques, mais devoir alterner régulièrement entre l’ancien formatage
%, la méthode.format(), et le nouveau style avec leurs subtiles différences est plus pénible que je ne l’imaginais, et les situations où on ne peut pas l’éviter reviennent souvent. L’ergonomie s’est améliorée, mais c’est frustrant de devoir encore utiliser les anciennes approchesOn peut le vérifier dans la documentation officielle à propos du nettoyage de ces limitations en 3.12
Il m’arrive de voir des collègues ou une IA utiliser des f-strings dans des appels au logger, alors que le logger a justement été conçu avec une interpolation paresseuse, et je trouve étrange de se priver volontairement de cette bonne fonctionnalité
Je considère les f-strings imbriquées comme une sorte de question piège. Je savais que la possibilité d’imbriquer avec le même style de guillemets avait été ajoutée, mais je ne savais plus dans quelle version. J’utilise encore l’astuce
f'{f"{}"}', parce que je veux que mon code reste compatible avec des versions un peu plus anciennes de PythonJe viens d’apprendre l’existence de la fonctionnalité qui permet, avec le signe égal (
=), d’afficher à la fois l’expression et sa valeur dans une f-stringJe pense que les notes de version Python valent vraiment la peine d’être lues. Il y a toujours de bonnes surprises. La fonctionnalité avec le signe égal a été ajoutée dans Python 3.8 lien associé
C’est dommage qu’une PEP similaire n’ait pas été adoptée pour les arguments nommés de fonction. Une syntaxe du type
foo(bar=)au lieu defoo(bar=bar)aurait permis de mieux faire ressortir les cas où l’on ne fait que transmettre un argument, et aurait été efficace pour le débogageJe trouve que c’est une fonctionnalité qui ne rapporte pas assez par rapport à la surprise qu’elle provoque. Elle risque de produire des comportements inattendus, donc j’ai peur qu’elle devienne une source de bugs. Une fonction standard qui n’afficherait qu’une partie de
locals()serait peut-être préférableC’est un motif énormément utilisé pour les sorties de débogage. En C++, j’ai pris l’habitude de mettre une expression entre guillemets et l’autre non. C’est plus facile à lire et cela évite de trop réfléchir
C’est vraiment utile quand on fait du débogage avec
print(f)Contrairement à l’URL, je pense qu’il y a en réalité très peu de questions vraiment dignes d’un WTF. Il y a bien quelques points vraiment surprenants, comme les questions 20 et 21
Le walrus operator m’est bien trop utile pour que j’y renonce. Il rend le code beaucoup plus propre pour le pattern matching et la gestion de branches multiples. Je ne m’en sers pas souvent, mais dans les situations adaptées il est très efficace
Ce n’est pas à cause du walrus operator, mais du comportement de
pythonstring.format; voir la documentation associéeJe n’ai pas vraiment utilisé Python de façon intensive depuis avant et après l’introduction des f-strings, mais j’ai réussi presque toutes les règles de syntaxe, et mes seules erreurs concernaient plutôt les valeurs de retour. Je me demande même si les f-strings ne sont pas la partie la moins WTF de Python
En créant une bibliothèque pour Lua proche des f-strings, j’ai appris pas mal de syntaxe, mais je ne m’attendais pas à
f"{...}"ni au walrus operator. Cela reste quand même loin du niveau d’étrangeté de Wat. La bibliothèque en question est iciJe ne pense pas qu’il y ait quoi que ce soit de particulièrement WTF ici. Une bonne partie concerne davantage la syntaxe du mini-langage de
str.format()que les f-strings elles-mêmesIl y a trop de fonctionnalités, au point d’avoir franchi un seuil critique. Aucun développeur n’a besoin de tout connaître, et comme il faut consulter la documentation à chaque fois qu’on doit réellement s’en servir, c’est inefficace. Comme on les utilise rarement, on oublie la syntaxe, et il est souvent bien plus rapide d’implémenter soi-même la même fonctionnalité, avec l’avantage que ce sera aussi plus facile à personnaliser pour les collègues. Un padding à gauche ? Une fonction en deux lignes suffit. Plutôt que d’hésiter sur la syntaxe de formatage — savoir si
nvient avant<, etc. — il est plus rapide de faire une implémentation ad hocDes choses comme le padding à gauche sont aussi disponibles avec la méthode
string.format, et cette approche existe depuis Python 2.6 (sorti en 2008) ; voir la documentation associée. Moi au contraire, la syntaxe de format me reste bien en tête et je la trouve utile. En plus, le formatage permet des points d’extension pour la personnalisationMoi, je voudrais un compromis. Le plus agréable serait d’avoir des fonctions
pad_left/pad_rightqui permettent aussi de définir directement le caractère de remplissage via un argument nommé. Comme c’est un besoin du quotidien, j’aimerais que ce soit dans la bibliothèque standard. Quand une bibliothèque de langage n’a pas ce genre de chose, on finit plus tard avec une multitude d’implémentations médiocres dans chaque projet, et cela devient comme JavaScript. Je n’aurai probablement jamais besoin du formatage Python avec^ou<>dans mon projet, mais dans des logiciels où la sortie en « monospace » est importante, cela peut au contraire être une fonctionnalité crucialeIl arrive qu’on utilise de façon répétée beaucoup de fonctionnalités bizarres ou de contournements dans une même base de code. Souvent, on les écrit une fois, puis on les copie-colle et on les réutilise sans fin
Si cette syntaxe avait été du JavaScript, la plupart auraient probablement déploré son manque d’intuition et ses fonctionnalités étranges
À mon avis, le vrai propos de ce quiz est que Python a presque autant de footguns que JavaScript. C’est peut-être parce qu’on voit souvent ce genre de billets « WTF » à propos de JS
Même en retirant les petites astuces, je pense que JavaScript reste de loin le roi des syntaxes peu intuitives. Les éléments des f-strings Python sont un peu particuliers eux aussi, mais ils n’apparaissent que dans des situations spécifiques, alors qu’en JS on a parfois le temps d’attendre l’installation des dépendances avant même de comparer deux tableaux
J’aimerais poser une question à propos des template literals de JavaScript. Contrairement à Python, on dirait qu’on ne peut pas faire quelque chose comme
let template = 'hello ${name}';, puistemplate.format({ name: 'joe' })pour remplir dynamiquement des valeurs plusieurs fois. J’ai donc fini par devoir l’implémenter moi-même. J’ai aussi regardé du côté des tagged templates, mais il restait difficile de réutiliser le template lui-même. Je comprends tout à fait qu’on se plaigne de la syntaxe JS ou de ses fonctionnalités étrangesSi c’était du Perl, cela aurait au contraire déclenché une pluie d’éloges
Je consulte pyformat.info(lien) ; ce n’est pas extrêmement exhaustif, mais on y trouve pratiquement tous les exemples raisonnables