Skip to content
Advertisement

Can f-strings auto-pad to [the next] even number of digits on output?

Based on this answer (among others) it seems like f-strings is [one of] the preferred ways to convert to hexadecimal representation.

While one can specify an explicit target length, up to which to pad with leading zeroes, given a goal of an output with an even number of digits, and inputs with an arbitrary # of bits, I can imagine:

  • pre-processing to determine the number of bits of the input, to feed an input-specific value in to the fstring, or
  • post-processing a-la out = "0"+f"{val:x}" if len(f"{val:x}") % 2 else f"{val:02x}" (or even using .zfill())

The latter seems like it might be more efficient than the former – is there a built-in way to do this with fstrings, or a better alternative?

Examples of input + expected output:

[0x]1 -> [0x]01
[0x]22 -> [0x]22
[0x]333 -> [0x]0333
[0x]4444 -> [0x]4444

and so on.

Advertisement

Answer

Here’s a postprocessing alternative that uses assignment expressions (Python 3.8+):

print((len(hx:=f"{val:x}") % 2) * '0' + hx)

If you still want a one-liner without assignment expressions you have to evaluate your f-string twice:

print((len(f"{val:x}") % 2) * '0' + f"{val:x}")

As a two-liner

hx = f"{val:x}"
print((len(hx) % 2) * '0' + hx)

And one more version:

print(f"{'0'[:len(hex(val))%2]}{val:x}")
Advertisement