What does \'=\' alignment
mean in the following error message, and why does this code cause it?
>&
str.__format__
doesn't know what to do with your 03
part. That only works with numbers:
>>> "{num:03}".format(num=1)
'001'
If you actually want to zero-pad a string, you can use rjust
:
>>> "1".rjust(3, "0")
'001'
The error message occurs because '=' alignment
has been implied by the format specifier.
The str.format
format spec mini-language parser has decided on the
alignment specifier “=” because:
Preceding the width field by a zero ('0') character enables sign-aware zero-padding for numeric types. This is equivalent to a fill character of '0' with an alignment type of '='.
So by specifying 0N
as the “zero-padding to N width”, you have implied both “the input is a numeric type”, and “the zeros should go between the sign and the digits”. That latter implication is what is meant by '=' alignment
.
Since the value "1"
is not numeric, the “=”-alignment handling code raises that exception. The message is written expecting you know what it's talking about because you requested (by implication) the “=” alignment.
Yes, I think that error message needs to be improved. I've raised an issue for that.
In my case, I was trying to zero-pad a string instead of a number.
The solution was simply to convert the text to a number before applying the padding:
num_as_text = '23'
num_as_num = int(num_as_text)
padded_text = f'{num_as_num:03}'
A workaround is to use '>'
(right justify) padding, which is with the syntax:
[[fill]align][width]
with align being >
, fill being 0
and width being 3
.
>>> "{num:0>3}".format(num="1")
'001'
The problem was that there is a different 0
in the format specification:
format_spec ::= [[fill]align][sign][#][0][width][grouping_option][.precision][type] # ^^^ This one
That zero just makes fill
default to 0
and align
to =
.
=
alignment is specified as:
Forces the padding to be placed after the sign (if any) but before the digits. This is used for printing fields in the form ‘+000000120’. This alignment option is only valid for numeric types. It becomes the default when ‘0’ immediately precedes the field width.
Source (Python 3 docs)
This expects the argument to be an int
, as strings don't have signs. So we just manually set it to the normal default of >
(right justify).
Also note that 0
just specifies the default values for fill
and align
. You can change both or just the align.
>>> # 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'
You are trying to insert 'string->"1" where a float->3.44 is required. Remove the quotes "1", i.e. num=1, and it will work
This format would be acceptable
"{num}:03".format(num="1")
but the way you have the placeholder specified {num:03}
is not. That is an interesting ValueError though, if you remove the :
the interesting error is replaced by a standard KeyError
.