- PEP 378 – Format Specifier for Thousands Separator
- Main Proposal (from Nick Coghlan, originally called Proposal I)
- Current Version of the Mini-Language
- Research into what Other Languages Do
- Alternative Proposal (from Eric Smith, originally called Proposal II)
- Commentary
- Copyright
- How to Print an Integer with Commas as Thousands Separators in Python?
- Method 1: f-Strings
- Method 2: string.format()
- Method 3: string.format() + string.replace() to Obtain Points as Thousand Separators
- Method 4: format()
- Where to Go From Here?
PEP 378 – Format Specifier for Thousands Separator
Provide a simple, non-locale aware way to format a number with a thousands separator.
Adding thousands separators is one of the simplest ways to humanize a program’s output, improving its professional appearance and readability.
In the finance world, output with thousands separators is the norm. Finance users and non-professional programmers find the locale approach to be frustrating, arcane and non-obvious.
The locale module presents two other challenges. First, it is a global setting and not suitable for multi-threaded apps that need to serve-up requests in multiple locales. Second, the name of a relevant locale (such as “de_DE”) can vary from platform to platform or may not be defined at all. The docs for the locale module describe these and many other challenges in detail.
It is not the goal to replace the locale module, to perform internationalization tasks, or accommodate every possible convention. Such tasks are better suited to robust tools like Babel. Instead, the goal is to make a common, everyday task easier for many users.
Main Proposal (from Nick Coghlan, originally called Proposal I)
A comma will be added to the format() specifier mini-language:
[[fill]align][sign][#][0][width][,][.precision][type]
The ‘,’ option indicates that commas should be included in the output as a thousands separator. As with locales which do not use a period as the decimal point, locales which use a different convention for digit separation will need to use the locale module to obtain appropriate formatting.
The proposal works well with floats, ints, and decimals. It also allows easy substitution for other separators. For example:
This technique is completely general but it is awkward in the one case where the commas and periods need to be swapped:
format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".")
The width argument means the total length including the commas and decimal point:
format(1234, "08,d") --> '0001,234' format(1234.5, "08,.1f") --> '01,234.5'
The ‘,’ option is defined as shown above for types ‘d’, ‘e’, ‘f’, ‘g’, ‘E’, ‘G’, ‘%’, ‘F’ and ‘’. To allow future extensions, it is undefined for other types: binary, octal, hex, character, etc.
This proposal has the virtue of being simpler than the alternative proposal but is much less flexible and meets the needs of fewer users right out of the box. It is expected that some other solution will arise for specifying alternative separators.
Current Version of the Mini-Language
Research into what Other Languages Do
Scanning the web, I’ve found that thousands separators are usually one of COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE.
C-Sharp provides both styles (picture formatting and type specifiers). The type specifier approach is locale aware. The picture formatting only offers a COMMA as a thousands separator:
String.Format(" ", 12400) ==> "12,400" String.Format("", 12400) ==> "12,400"
Common Lisp uses a COLON before the ~D decimal type specifier to emit a COMMA as a thousands separator. The general form of ~D is ~mincol,padchar,commachar,commaintervalD . The padchar defaults to SPACE. The commachar defaults to COMMA. The commainterval defaults to three.
(format nil "~:D" 229345007) => "229,345,007"
Visual Basic and its brethren (like MS Excel) use a completely different style and have ultra-flexible custom format specifiers like:
COBOL uses picture clauses like:
Java offers a Decimal.Format Class that uses picture patterns (one for positive numbers and an optional one for negatives) such as: «#,##0.00;(#,##0.00)» . It allows arbitrary groupings including hundreds and ten-thousands and uneven groupings. The special pattern characters are non-localized (using a DOT for a decimal separator and a COMMA for a grouping separator). The user can supply an alternate set of symbols using the formatter’s DecimalFormatSymbols object.
Alternative Proposal (from Eric Smith, originally called Proposal II)
Make both the thousands separator and decimal separator user specifiable but not locale aware. For simplicity, limit the choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. The SPACE can be either U+0020 or U+00A0.
Whenever a separator is followed by a precision, it is a decimal separator and an optional separator preceding it is a thousands separator. When the precision is absent, a lone specifier means a thousands separator:
[[fill]align][sign][#][0][width][tsep][dsep precision][type]
format(1234, "8.1f") --> ' 1234.0' format(1234, "8,1f") --> ' 1234,0' format(1234, "8.,1f") --> ' 1.234,0' format(1234, "8 ,f") --> ' 1 234,0' format(1234, "8d") --> ' 1234' format(1234, "8,d") --> ' 1,234' format(1234, "8_d") --> ' 1_234'
This proposal meets mosts needs, but it comes at the expense of taking a bit more effort to parse. Not every possible convention is covered, but at least one of the options (spaces or underscores) should be readable, understandable, and useful to folks from many diverse backgrounds.
As shown in the examples, the width argument means the total length including the thousands separators and decimal separators.
No change is proposed for the locale module.
The thousands separator is defined as shown above for types ‘d’, ‘e’, ‘f’, ‘g’, ‘%’, ‘E’, ‘G’ and ‘F’. To allow future extensions, it is undefined for other types: binary, octal, hex, character, etc.
The drawback to this alternative proposal is the difficulty of mentally parsing whether a single separator is a thousands separator or decimal separator. Perhaps it is too arcane to link the decimal separator with the precision specifier.
Commentary
- Some commenters do not like the idea of format strings at all and find them to be unreadable. Suggested alternatives include the COBOL style PICTURE approach or a convenience function with keyword arguments for every possible combination.
- Some newsgroup respondants think there is no place for any scripts that are not internationalized and that it is a step backwards to provide a simple way to hardwire a particular choice (thus reducing incentive to use a locale sensitive approach).
- Another thought is that embedding some particular convention in individual format strings makes it hard to change that convention later. No workable alternative was suggested but the general idea is to set the convention once and have it apply everywhere (others commented that locale already provides a way to do this).
- There are some precedents for grouping digits in the fractional part of a floating point number, but this PEP does not venture into that territory. Only digits to the left of the decimal point are grouped. This does not preclude future extensions; it just focuses on a single, generally useful extension to the formatting language.
- James Knight observed that Indian/Pakistani numbering systems group by hundreds. Ben Finney noted that Chinese group by ten-thousands. Eric Smith pointed-out that these are already handled by the “n” specifier in the locale module (albeit only for integers). This PEP does not attempt to support all of those possibilities. It focuses on a single, relatively common grouping convention that offers a quick way to improve readability in many (though not all) contexts.
Copyright
This document has been placed in the public domain.
How to Print an Integer with Commas as Thousands Separators in Python?
Problem Formulation: Given an integer number. How to convert the integer to a string representation for printing or other use that has thousand separators?
Method 1: f-Strings
Using the modern f-strings is, in my opinion, the most Pythonic solution to add commas as thousand-separators for all Python versions above 3.6: f» . The inner part within the curly brackets :, says to format the number and use commas as thousand separators.
Method 2: string.format()
You use the format specification language expression » to convert the integer number 1000000 to a string with commas as thousand separators.
- The outer part, the curly brackets » says to use the number passed into the format() function as a basis of the formatting process.
- The inner part within the curly brackets :, says to format the number and use commas as thousand separators.
Method 3: string.format() + string.replace() to Obtain Points as Thousand Separators
If you use points as a thousand-separator—for example in 1.000.000 as done in Europe—you can replace the commas in the comma-separated number using the suffix .replace(‘,’, ‘.’) in ».format(x).replace(‘,’,’.’) for any integer number x .
>>> ''.format(1000000).replace(',','.') '1.000.000'
A similar approach can be done with f-strings:
Method 4: format()
An alternative way to add commas as thousand separators is to use the ‘,d’ formatting syntax in the format() function.
Where to Go From Here?
Enough theory. Let’s get some practice!
Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.
To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?
You build high-value coding skills by working on practical coding projects!
Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?
🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.
If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.
While working as a researcher in distributed systems, Dr. Christian Mayer found his love for teaching computer science students.
To help students reach higher levels of Python success, he founded the programming education website Finxter.com that has taught exponential skills to millions of coders worldwide. He’s the author of the best-selling programming books Python One-Liners (NoStarch 2020), The Art of Clean Code (NoStarch 2022), and The Book of Dash (NoStarch 2022). Chris also coauthored the Coffee Break Python series of self-published books. He’s a computer science enthusiast, freelancer, and owner of one of the top 10 largest Python blogs worldwide.
His passions are writing, reading, and coding. But his greatest passion is to serve aspiring coders through Finxter and help them to boost their skills. You can join his free email academy here.
Be on the Right Side of Change 🚀
- The world is changing exponentially. Disruptive technologies such as AI, crypto, and automation eliminate entire industries. 🤖
- Do you feel uncertain and afraid of being replaced by machines, leaving you without money, purpose, or value? Fear not! There a way to not merely survive but thrive in this new world!
- Finxter is here to help you stay ahead of the curve, so you can keep winning as paradigms shift.
Learning Resources 🧑💻
⭐ Boost your skills. Join our free email academy with daily emails teaching exponential with 1000+ tutorials on AI, data science, Python, freelancing, and Blockchain development!
Join the Finxter Academy and unlock access to premium courses 👑 to certify your skills in exponential technologies and programming.
New Finxter Tutorials:
Finxter Categories: