Yesterday I wrote a blog post about creating short number formats in JavaScript. Definitely check out that post first, but the idea was to take something like 9496301
and display it as 9.5M
. In that post, I used the built-in Intl
object and it worked really well. It got me thinking, could you do the same in Python?
First off, I checked and was happy to see that like JavaScript, Python supports numeric separators. This makes it much easier to read large numbers in code. It also meant I could take my test array and copy and paste it into a Python program:
inputs = [ 999, 1000, 2999, 12_499, 12_500, 430912, 9_123_456, 1_111_111_111, 81_343_902_530, 1_111_111_111_111, 62_123_456_789_011, 1_111_111_111_111_111,]
I literally just now noticed that Python is also ok with the trailing comma. Sweet. Ok, so first I checked into just regular number formats, and of course, Python supports that, both with a built-in format
function and f
strings. In my case I wasn’t worried about decimal places and the like, but could easily add commas. Here’s a simple example:
for i in inputs: print(f"{i:<30}{i:,}")
The first time I print the value, I don’t format it, but pad it 30 characters to make my output easier to read. The formatting is done in the second variable, by just supplying :,
. Here’s the output:
999 9991000 1,0002999 2,99912499 12,49912500 12,500430912 430,9129123456 9,123,4561111111111 1,111,111,11181343902530 81,343,902,5301111111111111 1,111,111,111,11162123456789011 62,123,456,789,0111111111111111111 1,111,111,111,111,111
Commas work for some countries, but not all. I checked and there’s a locale-specific version as well: :n
. Here’s an example where I set the locale to German.
999 9991000 1.0002999 2.99912499 12.49912500 12.500430912 430.9129123456 9.123.4561111111111 1.111.111.11181343902530 81.343.902.5301111111111111 1.111.111.111.11162123456789011 62.123.456.789.0111111111111111111 1.111.111.111.111.111
One odd thing with the n
operator is that when I didn’t specify a locale, it used nothing. I’m not sure why. Running locale.getlocale()
definitely returned en_US
, but maybe the expectation is that you should always set a locale when using it. I tried this and it worked:
locale.setlocale(locale.LC_ALL,locale.getlocale())
I’m chalking that up to something I did wrong, or misunderstood.
Ok, so that’s basic formatting, how would you do the nice ‘short’ format? Use the numerize
library. You can find it here, https://github.com/davidsa03/numerize, and after installing it via pip
, here’s an example of it in use:
from numerize.numerize import numerize# numbers defined here...for i in inputs: print(f"{i:<30}{numerize(i)}")
And the output:
999 9991000 1K2999 3K12499 12.5K12500 12.5K430912 430.91K9123456 9.12M1111111111 1.11B81343902530 81.34B1111111111111 1.11T62123456789011 62.12T1111111111111111 1111111111111111
Noticed that it worked perfectly… except for the final huge number, but as I mentioned in the last post, JavaScript’s Intl
also didn’t handle it exactly right, although I do think it handled it better, returning 1111T
instead. Either way, numerize
is pretty nifty and was quick to use.