Les nombreuses méthodes de formatage des chaînes de Python - les plus anciennes sont-elles (vont-elles être) obsolètes?


106

Python a au moins six façons de formater une chaîne:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

Un bref historique des différentes méthodes:

  • printf-le formatage de style existe depuis l'enfance des Pythons
  • La Templateclasse a été introduite dans Python 2.4
  • La formatméthode a été introduite dans Python 2.6
  • f-strings ont été introduits dans Python 3.6

Mes questions sont:

  • La printfmise en forme -style est-elle obsolète ou va-t-elle l'être?
  • Dans le Template class, la substituteméthode est-elle obsolète ou va-t-elle l'être? (Je ne parle pas de safe_substitute, qui, d'après ce que je comprends, offre des capacités uniques)

Questions similaires et pourquoi je pense qu'il ne s'agit pas de doublons:

Voir également


1
Dois-je signaler que vous avez oublié le Formattercours?
Martijn Pieters

Réponses:


14

Bien qu'il existe diverses indications dans la documentation selon lesquelles les .formatf-strings sont supérieures aux %chaînes, il n'y a pas de plan survivant pour déprécier ces dernières.

Dans le problème de validation n ° 14123: mentionnez explicitement que le formatage de chaîne de style% ancien comporte des mises en garde mais qu'il ne disparaîtra pas de si tôt. , inspiré du problème Indique qu'il n'y a actuellement aucun projet de déprécier le formatage de style printf , la documentation sur le %formatage a été modifiée pour contenir cette phrase:

Comme la nouvelle syntaxe de formatage de chaîne est plus flexible et gère naturellement les tuples et les dictionnaires, elle est recommandée pour le nouveau code. Cependant, il n'est actuellement pas envisagé d'abandonner le formatage de style printf .

(Soulignez le mien.)

Cette phrase a été supprimée plus tard, dans commit Close # 4966: réorganiser la documentation de la séquence afin de mieux expliquer l'état de Python moderne . Cela peut sembler un signe qu'un plan visant à déprécier le %formatage était de retour sur les cartes ... mais plonger dans le suivi des bogues révèle que l'intention était le contraire. Sur le bug tracker, l'auteur du commit caractérise le changement comme ceci :

  • a changé la prose qui décrit la relation entre le formatage de style printf et la méthode str.format (en supprimant délibérément l'implication selon laquelle le premier risque réel de disparaître - il n'est tout simplement pas pratique pour nous d'envisager sérieusement de le tuer)

En d'autres termes, nous avons eu deux changements consécutifs dans les %documents de mise en forme destinés à souligner explicitement qu'il ne sera pas obsolète, et encore moins supprimé. Les documents restent avisés sur les mérites relatifs des différents types de formatage de chaîne, mais ils sont également clairs que le %formatage ne sera pas obsolète ou supprimé.

De plus, la dernière modification apportée à ce paragraphe , en mars 2017, l'a changé à partir de cela ...

Les opérations de formatage décrites ici présentent une variété de bizarreries qui conduisent à un certain nombre d'erreurs courantes (telles que le fait de ne pas afficher correctement les tuples et les dictionnaires). L'utilisation des nouveaux littéraux de chaîne formatés ou de l' str.formatinterface permet d'éviter ces erreurs. Ces alternatives fournissent également des approches plus puissantes, flexibles et extensibles pour la mise en forme du texte.

... pour ça:

Les opérations de formatage décrites ici présentent une variété de bizarreries qui conduisent à un certain nombre d'erreurs courantes (telles que le fait de ne pas afficher correctement les tuples et les dictionnaires). L'utilisation des nouveaux littéraux de chaîne formatés, de l' str.formatinterface ou des chaînes de modèle peut aider à éviter ces erreurs. Chacune de ces alternatives offre ses propres compromis et avantages de simplicité, de flexibilité et / ou d'extensibilité.

Notez que le changement de "aide à éviter" à "peut aider à éviter", et comment la recommandation claire de .formatet f-strings a été remplacée par une prose duveteuse et équivoque sur la façon dont chaque style "fournit ses propres compromis et avantages" . Autrement dit, non seulement une dépréciation formelle n'est plus sur les cartes, mais la documentation actuelle reconnaît ouvertement que le %formatage a au moins quelques "avantages" par rapport aux autres approches.

Je déduire de tout cela que le mouvement pour désapprouver ou supprimer le %formatage a non seulement échoué, mais a été complètement et définitivement vaincu.


2
Le changement de langue duveteux a été ajouté pour apaiser les responsables de Mercurial (entre autres) qui ne voulaient pas que Mercurial soit laissé pour compte avec une base de code trop volumineuse pour être supprimée %. Maintenant que la politique «pas de mods de code à grande échelle» a été abandonnée, leurs objections s'estompent également. À long terme, le maintien de ces deux formes sans prestations qui restent pour % à un moment donné la syntaxe printf sera supprimée de toute façon. Nous ne savons tout simplement pas quand encore, et donc la langue valait la peine d'être atténuée.
Martijn Pieters

@MartijnPieters Intéressant. Il semble que vous ayez une grande connaissance de cette décision qui me manque. Pour ce que cela vaut, je pense qu'une réponse bien référencée de votre part décrivant ces points (soit comme une nouvelle réponse, soit comme une modification de votre réponse existante) aurait de la valeur.
Mark Amery

58

La nouvelle .format()méthode est destinée à remplacer l'ancienne %syntaxe de formatage. Ce dernier a été désaccentué, (mais pas officiellement désapprouvée encore ). La documentation de la méthode le déclare:

Cette méthode de mise en forme de chaîne est la nouvelle norme de Python 3 et doit être préférée à la %mise en forme décrite dans Opérations de mise en forme de chaîne dans le nouveau code.

(Je souligne le mien).

Pour maintenir la compatibilité ascendante et faciliter la transition, l'ancien format a été laissé en place pour le moment . D'après la proposition originale PEP 3101 :

Rétrocompatibilité

La rétrocompatibilité peut être maintenue en laissant les mécanismes existants en place. Le nouveau système n'entre en conflit avec aucun des noms de méthode des techniques de formatage de chaîne existantes, de sorte que les deux systèmes peuvent coexister jusqu'à ce qu'il soit temps de désapprouver l'ancien système.

Notez le jusqu'à ce qu'il soit temps de désapprouver l'ancien système ; il n'est pas obsolète, mais le nouveau système doit être utilisé chaque fois que vous écrivez un nouveau code .

Le nouveau système a pour avantage que vous pouvez combiner l'approche tuple et dictionnaire de l'ancien %formateur:

"{greeting}, {0}".format(world, greeting='Hello')

et est extensible via le object.__format__()crochet utilisé pour gérer le formatage des valeurs individuelles.

Notez que l'ancien système avait %et leTemplate classe, où cette dernière vous permet de créer des sous-classes qui ajoutent ou modifient son comportement. Le système de style nouveau a la Formatterclasse pour occuper le même créneau.

Python 3 s'est encore éloigné de la dépréciation, vous donnant plutôt un avertissement dans le printfformatage de chaîne -style section :

Remarque : Les opérations de mise en forme décrites ici présentent une variété de bizarreries qui conduisent à un certain nombre d'erreurs courantes (telles que le fait de ne pas afficher correctement les tuples et les dictionnaires). L'utilisation des nouveaux littéraux de chaîne formatés ou de l' str.format()interface permet d'éviter ces erreurs. Ces alternatives fournissent également des approches plus puissantes, flexibles et extensibles pour la mise en forme du texte.

Python 3.6 a également ajouté des littéraux de chaîne formatés , qui alignent les expressions dans les chaînes de format. Il s'agit de la méthode la plus rapide de création de chaînes avec des valeurs interpolées et doit être utilisée à la place de str.format()partout où vous pouvez utiliser un littéral.


4
Et avec Formattervous pouvez créer des formats personnalisés tels que ceux datetimeutilisés par les objets. De plus, puisque .formatc'est une fonction, vous pouvez l'utiliser pour créer un formatage paresseux appelable plus directement: par exemple,fmt = '{} - {}'.format; fmt(a, b)
Jon Clements

Je ne vois pas comment Templateest lié à %ou à l' ancien système . En particulier, le PEP que vous liez les états Bien qu'il y ait un certain chevauchement entre cette proposition et string.Template, on estime que chacun répond à un besoin distinct, et que l'un ne supprime pas l'autre. Dans votre réponse, on peut être confus que le Templateformatage, faisant partie de l' ancien système , est également obsolète.
Bakuriu

@Bakuriu: Oui, je pense que j'ai raté cette partie; mais à mon avis, la Formatterclasse peut combler les mêmes besoins que string.Template().
Martijn Pieters

1
[...]should be preferred to the % formatting[...]cette partie a été supprimée de la documentation. docs.python.org/3/library/stdtypes.html#str.format
AXO

Je pense que cette réponse est actuellement trompeuse; le premier passage cité a été supprimé de la documentation Python 3, et il me semble assez clair qu'il n'y a pas d'intention restante pour qu'une dépréciation ait lieu. Cette réponse a toujours une valeur historique, mais je serais enclin à modifier le libellé pour éviter toute suggestion qu'une dépréciation est toujours dans les cartes, et à modifier une grande partie de la première moitié de la réponse pour qu'elle soit au passé. Je le ferai moi-même à un moment donné si vous ne vous opposez pas, mais j'ai pensé que je ferais d'abord un commentaire pour vous donner une chance d'apporter de tels changements vous-même si vous le souhaitez.
Mark Amery

45

L' %opérateur de formatage de chaîne n'est pas obsolète et ne sera pas supprimé - malgré les autres réponses.
Chaque fois que le sujet est soulevé sur la liste de développement Python, il y a une forte controverse sur ce qui est mieux, mais aucune controverse sur l'opportunité de supprimer la méthode classique - cela restera. Bien qu'il soit indiqué sur PEP 3101, Python 3.1 était venu et reparti, et le %formatage est toujours là.

Les déclarations pour le style classique de conservation sont claires: c'est simple, c'est rapide, c'est rapide à faire pour des choses courtes. Utiliser la .formatméthode n'est pas toujours plus lisible - et presque personne - même parmi les développeurs principaux, peut utiliser la syntaxe complète fournie par .formatsans avoir à regarder la référence Même en 2009, on avait des messages comme celui-ci: http: // mail. python.org/pipermail/python-dev/2009-Octobre/092529.html - le sujet était à peine apparu dans les listes depuis.

Mise à jour 2016

Dans la version actuelle de développement de Python (qui deviendra Python 3.6), il existe une troisième méthode d'interpolation de chaîne, décrite sur PEP-0498 . Il définit un nouveau préfixe de guillemet f""(en plus de l'actuel u"", b""et r"").

Le préfixe d'une chaîne par fappellera une méthode sur l'objet chaîne au moment de l'exécution, qui interpolera automatiquement les variables de la portée actuelle dans la chaîne:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

3
Il est beaucoup plus agréable de permettre aux types d'implémenter les leurs __format__. Par exemple, format(Decimal('0.1'), '.20f')vs '%.20f' % Decimal('0.1'). Ce dernier contraint le Decimal à un flotteur.
Eryk Sun

2
NB. Je n'ai pas soutenu que l'ancien style est meilleur à tous égards - juste qu'il est plus court et parfois plus lisible (et parfois pas). Certes, la nouvelle méthode est beaucoup plus flexible.
jsbueno

Existe-t-il un équivalent pour fen Python 3?
Daniel

Les éléments f-stringsutilisés ci-dessus sont une nouvelle fonctionnalité du langage à partir de Python 3.6. Il n'existe pas dans les versions précédentes et provoquera une erreur de syntaxe sur celles-ci.
jsbueno

20

La dernière position de Guido à ce sujet semble être indiquée ici:

Nouveautés de Python 3.0

PEP 3101: Une nouvelle approche du formatage des chaînes

Un nouveau système pour les opérations de formatage de chaîne intégrées remplace l'opérateur de formatage de chaîne%. (Cependant, l'opérateur% est toujours pris en charge; il sera obsolète dans Python 3.1 et supprimé du langage ultérieurement.) Lisez PEP 3101 pour le scoop complet.

Et le PEP3101 lui-même, qui a la dernière modification datant de (ven, 30 septembre 2011), donc aucun progrès ces derniers temps sur celui-là, je suppose.


18

En regardant les anciens documents Python et PEP 3101, il y avait une déclaration selon laquelle l'opérateur% sera obsolète et supprimé du langage à l'avenir. L' instruction suivante figurait dans la documentation Python pour Python 3.0, 3.1 et 3.2:

Puisque str.format () est assez nouveau, beaucoup de code Python utilise toujours l'opérateur%. Cependant, étant donné que cet ancien style de formatage sera finalement supprimé du langage, str.format () doit généralement être utilisé.

Si vous accédez à la même section dans les documents Python 3.3 et 3.4, vous verrez que l'instruction a été supprimée. Je ne trouve également aucune autre déclaration nulle part ailleurs dans la documentation indiquant que l'opérateur sera obsolète ou supprimé de la langue. Il est également important de noter que PEP3101 n'a pas été modifié depuis plus de deux ans et demi (ven, 30 sept. 2011).

Mettre à jour

PEP461 L'ajout de% de mise en forme aux octets et aux bytes est accepté et devrait faire partie de Python 3.5 ou 3.6. C'est un autre signe que l'opérateur% est bien vivant.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.