python / python/cpython

Improve `printf`-style formatting docs for non-built-in types

Open
#142,108 18 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

docs
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Add a description about how Decimal behaves differently with format and % formatting in https://docs.python.org/3/library/string.html#format-specification-mini-language

For __format__, Decimal is formatted with the highest possible precision as it is.

For % formatting, Decimal is converted to float before formatting.

These behaviors have not changed since they were added.

Compare:

sys.version '%f' % 11111111111111111111.0 '%f' % Decimal('11111111111111111111.0') Decimal('11111111111111111111.0').__format__('f') '%e' % 0.0 '%e' % Decimal('0.0') Decimal('0.0').__format__('e') '%.20e' % 11111111111111111111.0 '%.20e' % Decimal('11111111111111111111.0') Decimal('11111111111111111111.0').__format__('.20e') '%.20g' % 11111111111111111111.0 '%.20g' % Decimal('11111111111111111111.0') Decimal('11111111111111111111.0').__format__('.20g')
'2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)]' '11111111111111111000.000000' '11111111111111111000.000000' Exception '0.000000e+000' '0.000000e+000' Exception '1.11111111111111110000e+019' '1.11111111111111110000e+019' Exception '11111111111111111000' '11111111111111111000' Exception
'2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)]' '11111111111111111000.000000' '11111111111111111000.000000' '11111111111111111111.0' '0.000000e+00' '0.000000e+00' '0e-1' '1.11111111111111110000e+19' '1.11111111111111110000e+19' '1.11111111111111111110e+19' '11111111111111111000' '11111111111111111000' '11111111111111111111'
'2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)]' '11111111111111110656.000000' '11111111111111110656.000000' '11111111111111111111.0' '0.000000e+00' '0.000000e+00' '0e-1' '1.11111111111111106560e+19' '1.11111111111111106560e+19' '1.11111111111111111110e+19' '11111111111111110656' '11111111111111110656' '11111111111111111111'
'3.14.0 (tags/v3.14.0:ebf955d, Oct 7 2025, 10:06:33) [MSC v.1944 32 bit (Intel)]' '11111111111111110656.000000' '11111111111111110656.000000' '11111111111111111111.0' '0.000000e+00' '0.000000e+00' '0e-1' '1.11111111111111106560e+19' '1.11111111111111106560e+19' '1.11111111111111111110e+19' '11111111111111110656' '11111111111111110656' '11111111111111111111'
'3.14.0 (tags/v3.14.0:ebf955d, Oct 7 2025, 10:15:03) [MSC v.1944 64 bit (AMD64)]' '11111111111111110656.000000' '11111111111111110656.000000' '11111111111111111111.0' '0.000000e+00' '0.000000e+00' '0e-1' '1.11111111111111106560e+19' '1.11111111111111106560e+19' '1.11111111111111111110e+19' '11111111111111110656' '11111111111111110656' '11111111111111111111'
'3.15.0a2 (tags/v3.15.0a2:a625628, Nov 18 2025, 18:12:01) [MSC v.1944 64 bit (AMD64)]' '11111111111111110656.000000' '11111111111111110656.000000' '11111111111111111111.0' '0.000000e+00' '0.000000e+00' '0e-1' '1.11111111111111106560e+19' '1.11111111111111106560e+19' '1.11111111111111111110e+19' '11111111111111110656' '11111111111111110656' '11111111111111111111'
# ./test.py
import sys
from decimal import Decimal

for expr in (
    "sys.version",

    "'%f' % 12345123451234512345.0",
    "'%f' % Decimal('12345123451234512345.0')",
    "Decimal('12345123451234512345.0').__format__('f')",

    "'%e' % 0.0",
    "'%e' % Decimal('0.0')",
    "Decimal('0.0').__format__('e')",

    "'%.20e' % 12345123451234512345.0",
    "'%.20e' % Decimal('12345123451234512345.0')",
    "Decimal('12345123451234512345.0').__format__('.20e')",

    "'%.20g' % 12345123451234512345.0",
    "'%.20g' % Decimal('12345123451234512345.0')",
    "Decimal('12345123451234512345.0').__format__('.20g')",
):
    print(expr)
    try:
        print(repr(eval(expr)))
    except Exception:
        print('Exception')
    print('')
# ./test_runner.py
from pathlib import Path
from subprocess import run, PIPE

PYTHON_DIR_ROOT = r"C:\python_dir_root"

def print_row(row, file):
    for v in row: print(f"| {v} ", end='', file=file)
    print("|", file=file)

def print_md_table(headers, rows, file):
    print_row(headers, file=file)
    print_row(['---:'] * len(headers), file=file)
    for row in rows: print_row(row, file=file)
    print(file=file)

rows = []
for dir in Path(PYTHON_DIR_ROOT).iterdir():
    out = run([str(dir/"python.exe"), "./test.py"], stdout=PIPE).stdout
    out = out.decode('utf-8').splitlines()
    headers = [f"`{h}`" for h in out[::3]]
    rows.append(out[1::3])

with open("./test_result.md", 'w', encoding='utf-8') as fp:
    print_md_table(headers, rows, file=fp)
Linked PRs
  • gh-142117
  • gh-142126

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the format specification mini-language section of docs.python.org/3/library/string.html and review the Decimal examples and formatting behavior described in the issue. Check linked PRs gh-142117 and gh-142126 first; the work is done when the documentation clearly distinguishes format from % formatting for Decimal.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.