web-dev-qa-db-fra.com

Utilisation de! S vs.: s pour formater une chaîne en Python

Je suis vraiment curieux de savoir au sujet de la chaîne de formatage :s En Python 3. La documentation dit que !s Est conversion et que :s est format_spec.

Il indique également que !s Appliquera str(), mais il ne dit rien de similaire à propos de :s. Je pense qu'il n'y a pas de différence significative entre eux, mais je veux en être sûr. Quelqu'un peut-il clarifier cela?

Un exemple de code:

print("{!s}".format("this"))
print("{:s}".format("that"))
# I want to be sure that these two are processed identically internally

C'est toujours déroutant, mais permettez-moi de conclure avec mes propres mots (profanes).

  1. type("whatever".format) est toujours str.
  2. Utilisez !s Si vous souhaitez convertir l'objet en str avant de formater.
  3. :s Signifie que l'objet (ou l'objet converti) sera traité comme str pendant un processus de formatage interne. C'est la valeur par défaut format_spec.

Quelque chose ne va pas ici?

36
Sangbok Lee

!s Et ses frères !a Et !r Appliquent respectivement str(), ascii() et repr() avant interpolation et formatage. Ceux-ci sont appelés drapeaux de conversion, et font partie de la spécification Format String Syntax , pas le par champ formatage spec appliqué aux valeurs lors de l'interpolation:

Le champ conversion provoque une contrainte de type avant le formatage . Normalement, le travail de formatage d'une valeur est effectué par la méthode __format__() de la valeur elle-même. Cependant, dans certains cas, il est souhaitable de forcer un type à être formaté sous forme de chaîne, en remplaçant sa propre définition de formatage. En convertissant la valeur en un avant d'appeler __format__(), la logique de formatage normale est contournée.

Accentuation sur moi.

:s S'applique uniquement par la suite au résultat de la conversion (ou à l'objet d'origine si aucune conversion n'a été appliquée), et uniquement si la méthode __format__ Pour le type d'objet prend en charge cette option de formatage. Habituellement, seuls les objets de type str prennent en charge ce formateur; il est là par défaut, principalement parce que le Format Specification Mini-Language permet l'existence d'un caractère de type et parce que l'ancien %printf- formatage de style avait un format %s. Si vous essayez d'appliquer le type s à un objet qui ne le prend pas en charge, vous obtiendrez une exception.

Utilisez !s (Ou !a Ou !r) Lorsque vous avez un objet qui n'est pas lui-même une chaîne et ne prend pas en charge le formatage autrement (tous les types ne le font pas) ou le ferait formater différemment de leurs conversions str(), ascii() ou repr():

>>> class Foo:
...     def __str__(self):
...         return "Foo as a string"
...     def __repr__(self):
...         return "<Foo as repr, with åéæ some non-ASCII>"
...     def __format__(self, spec):
...         return "Foo formatted to {!r} spec".format(spec)
...
>>> print("""\
... Different conversions applied:
... !s: {0!s:>60s}
... !r: {0!r:>60s}
... !a: {0!a:>60s}
... No conversions: {0:>50s}
... """.format(Foo()))
Different conversions applied:
!s:                                    Foo as a string
!r:             <Foo as repr, with åéæ some non-ASCII>
!a:    <Foo as repr, with \xe5\xe9\xe6 some non-ASCII>
No conversions: Foo formatted to '>50s' spec

Remarque: tous le formatage spécifié par la spécification de format est la responsabilité de la méthode __format__; la dernière ligne n'applique pas l'opération d'alignement dans la spécification de formatage >50s, la méthode Foo.__format__ ne l'a utilisée que comme texte littéral dans une opération de formatage (en utilisant ici une conversion !r) .

Pour les valeurs converties, en revanche, la méthode str.__format__ Est utilisée et la sortie est alignée à droite dans un champ de 50 caractères de large, avec des espaces à gauche.

33
Martijn Pieters

Vous n'avez pas de chance d'avoir utilisé des chaînes comme valeur à formater. En utilisant à peu près n'importe quel autre objet, vous obtiendriez comment ceux-ci ne sont pas les mêmes.

En termes (autant que je peux) en termes simples:

  • L'absence ou l'existence de l'indicateur de conversion spécifie le type de la valeur que nous allons formater et, par extension, qui est __format__ nous appellerons. Comme le souligne Martjin, en utilisant cela, nous pouvons contourner certains comportements et traiter la valeur de manière plus générique (comme une chaîne). Il existe en trois saveurs différentes qui correspondent aux trois façons différentes dont un objet peut choisir de se représenter sous forme de chaîne.
  • Le spécificateur de type, couplé à d'autres spécificateurs, spécifie comment le type que nous avons doit finalement être présenté. Pour les chaînes, il n'y a pas un riche ensemble d'options (une chaîne est présentée telle quelle) mais, pour les types comme ints, vous pouvez avoir différentes présentations.

Je pense, cependant, que type est probablement un nom déroutant pour donner ce spécificateur.

2