Okay sorry for flip-flopping here: my previous message which suggested implementing ‘exact precision’ with .
was based off if we had to choose only one behaviour for .
for integers, lest we add some new syntax like !
to achieve both. I hadn’t considered that we could use the z
format specifier (which is currently unused for integers) in order to implement both. So disregard my last message.
I think we do. .
for precision and z.
for modulo followed by precision.
I agree. f"{25:#.2x}"
is '0x19'
and f"{1025:#.2x}"
should be '0x401'
, not an OverflowError
/ ValueError
. So ‘precision’ .
(without a z
) will be identical to %-formatting. Although I said I was okay with f-strings / str.format
differing from %-formatting, that was only if we had to choose exactly one behaviour, i.e. without z
having an effect to activate twos-complements mode; there’s no point purposely making % and str.format
differ from each other.
Yes.
f"{25:#.2x}"
is"%#.2x" % 25
is'0x19'
f"{1025:#.2x}"
is"%#.2x" % 1025
is'0x401'
. No truncation to exactly 2 digits, as 2 is only the minimum, So the PR needs to be changed to not be anOverflowError
/ValueError
f"{-1025:#.2x}"
is"%#.2x" % -1025
is'-0x401'
. Same behaviour as %-formatting. I don’t think I’ve ever used negative hex format, but there’s no point breaking compatibility if we can avoid it.f"{1025:#.2}"
is"%#.2d" % 1025
is'1025'
. Normal.f"{-1:#.4}"
is"%#.4d" % -1
is'-0001'
. Normal.
I disagree with this. This is like the ‘Minimal width binary representation’ I talked about in a previous message. It’s okay when you know what you’re looking for, but even I got confused at the example on GitHub
>>> format(-129, '.8b')
'101111111'
That threw me off, I started reading it as 256 + 127 = 383. That’s why I suggested against ‘minimal width binary representation’
So I would go back to my proposal to implement .
as ‘precision’, behaviour 3, the same as %-formatting, and behaviour 4 (take modulo base ** n
first, then pass to .
) as z.
instead of adding a new !
.
Also
I think I made a strong case in OP that having to re-calculate the width to account for the prefix is un-user-friendly, so this whole proposal is motivated
One of my original examples was a hexdump function, which fails for any non-ASCII bytes if a signed range were enforced
def hexdump(b: bytes) -> str:
return " ".join(f"{i:#.2x}" for i in b)
hexdump("привет".encode()) # ValueError: Expected integer in range(-2**7, 2**7)
The solution is to implement the z
format specifier for ints iff used with precision as z.
with behaviour 4 that I laid out here
TLDR
So tldr: I suggest implementing the previous proposal, but with z.
instead of adding a new !
.
should do the same job in f-strings andstr.format
as it does with%
, precision being the number of digits, as laid out in OPz.
should take modulo first, moving x intorange(0, base ** n)
, and then formats that with precision, ief"{x:z.{n}{base}}"
isf"{divmod(x, base ** n)[1]:.{n}{base}}"