web-dev-qa-db-fra.com

Erreur de mise en forme du texte: l'alignement «=» n'est pas autorisé dans le spécificateur de format de chaîne

Qu'est-ce que '=' alignment signifie dans le message d'erreur suivant, et pourquoi ce code le provoque-t-il?

>>> "{num:03}".format(num="1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: '=' alignment not allowed in string format specifier

Le code a un problème subtil: la valeur d'entrée "1" est du texte, pas un nombre. Mais le message d'erreur ne semble avoir rien à voir avec cela.

Rien dans le message d'erreur n'indique pourquoi "'=' alignement" est pertinent et n'apparaît pas dans le code. Quelle est donc l'importance d'émettre ce message d'erreur?

26
bignose

Le message d'erreur se produit car '=' alignment a été impliqué par le spécificateur de format.

Le str.formatformat mini-langue de spécification l'analyseur a choisi le spécificateur d'alignement "=" car:

Le fait de faire précéder le champ de largeur d'un caractère zéro ("0") permet un remplissage nul sensible aux signes pour les types numériques. Cela équivaut à un caractère de remplissage de "0" avec un type d'alignement de "=".

Donc, en spécifiant 0N en tant que "remplissage nul à la largeur N", vous avez sous-entendu à la fois "l'entrée est de type numérique" et "les zéros doivent aller entre le signe et les chiffres". Cette dernière implication est ce que l'on entend par '=' alignment.

Puisque la valeur "1" n'est pas numérique, le "=" - le code de gestion de l'alignement lève cette exception. Le message est écrit en attendant que vous sachiez de quoi il parle parce que vous avez demandé (par implication) l'alignement "=".

Oui, je pense que ce message d'erreur doit être amélioré. J'ai soulevé un problème pour cela .

37
bignose

Une solution de contournement consiste à utiliser '>' (justifier à droite) le remplissage, qui est avec la syntaxe:

[[fill]align][width]

avec alignement étant >, remplir étant 0 et la largeur étant 3.

>>> "{num:0>3}".format(num="1")
'001'

Le problème était qu'il existe un autre 0 dans la spécification de format:

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
#                                          ^^^ This one

Ce zéro fait juste fill par défaut à 0 et align à =.

= l'alignement est spécifié comme suit:

Force le remplissage à être placé après le signe (le cas échéant) mais avant les chiffres. Il est utilisé pour imprimer des champs sous la forme ‘+000000120’. Cette option d'alignement n'est valable que pour les types numériques. Il devient la valeur par défaut lorsque "0" précède immédiatement la largeur du champ.

Source (documents Python 3)

Cela attend que l'argument soit un int, car les chaînes n'ont pas de signe. Nous venons donc de le définir manuellement sur la valeur par défaut normale de > (justifier à droite).

Notez également que 0 spécifie simplement les valeurs par défaut de fill et align. Vous pouvez modifier les deux ou simplement l'alignement.

>>> # fill defaults to '0', align is '>', `0` is set, width is `3`
>>> "{num:>03}".format(num=-1)
'0-1'
>>> # fill is `x`, align is '>', `0` is set (but does nothing), width is `"3"`
>>> "{num:x>03}".format(num=-1)
'x-1'
>>> # fill is `x`, align is '>', `0` is set (but does nothing), width is `"03"` (3)
>>> "{num:x>003}".format(num=-1)
'x-1'
10
Artyer

str.__format__ ne sait pas quoi faire de votre 03 partie. Cela ne fonctionne qu'avec des chiffres:

>>> "{num:03}".format(num=1)
'001'

Si vous voulez réellement mettre à zéro une chaîne, vous pouvez utiliser rjust:

>>> "1".rjust(3, "0")
'001'
5
L3viathan

Vous essayez d'insérer 'string -> "1" où un flottant-> 3.44 est requis. Supprimez les guillemets "1", c'est-à-dire num = 1, et cela fonctionnera

0
diahron