From 92b3f8f559aa6cb8050a560448950d81b1726259 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Sun, 26 Apr 2026 20:55:04 +0200 Subject: [PATCH 1/3] Improve fractions startup time --- Lib/fractions.py | 32 +++++++++++++++----------------- Lib/test/test_fractions.py | 2 ++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/fractions.py b/Lib/fractions.py index c1b12e7a1c0..a1c854e3295 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -54,18 +54,18 @@ def _hash_algorithm(numerator, denominator): return -2 if result == -1 else result _RATIONAL_FORMAT = re.compile(r""" - \A\s* # optional whitespace at the start, - (?P[-+]?) # an optional sign, then - (?=\d|\.\d) # lookahead for digit or .digit - (?P\d*|\d+(_\d+)*) # numerator (possibly empty) - (?: # followed by - (?:\s*/\s*(?P\d+(_\d+)*))? # an optional denominator - | # or - (?:\.(?P\d*|\d+(_\d+)*))? # an optional fractional part - (?:E(?P[-+]?\d+(_\d+)*))? # and optional exponent + \A\s*+ # optional whitespace at the start, + (?P[-+]?+) # an optional sign, then + (?=\d|\.\d) # lookahead for digit or .digit + (?P(?:\d++(?:_\d++)*+)?+) # numerator (possibly empty) + (?: # followed by + \s*+/\s*+(?P\d++(?:_\d++)*+) # a denominator + | # or + (?:\.(?P(?:\d++(?:_\d++)*+)?+))?+ # an optional fractional part + (?:[eE](?P[-+]?+\d++(?:_\d++)*+))?+ # and optional exponent ) - \s*\z # and optional whitespace to finish -""", re.VERBOSE | re.IGNORECASE) + \s*+\z # and optional whitespace to finish +""", re.VERBOSE) # Helpers for formatting @@ -255,26 +255,24 @@ def __new__(cls, numerator=0, denominator=None): if m is None: raise ValueError('Invalid literal for Fraction: %r' % numerator) - numerator = int(m.group('num') or '0') - denom = m.group('denom') + sign, num, denom, decimal, exp = m.groups() + numerator = int(num) if num else 0 if denom: denominator = int(denom) else: denominator = 1 - decimal = m.group('decimal') if decimal: decimal = decimal.replace('_', '') scale = 10**len(decimal) numerator = numerator * scale + int(decimal) - denominator *= scale - exp = m.group('exp') + denominator = scale if exp: exp = int(exp) if exp >= 0: numerator *= 10**exp else: denominator *= 10**-exp - if m.group('sign') == '-': + if sign == '-': numerator = -numerator elif isinstance(numerator, numbers.Rational): diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index cf42b86358d..d0b573ff474 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -434,6 +434,7 @@ def check_invalid(s): # Imitate float's parsing. check_invalid("+ 3/2") check_invalid("- 3/2") + check_invalid("+ 343.33") # Avoid treating '.' as a regex special character. check_invalid("3a2") # Don't accept combinations of decimals and rationals. @@ -445,6 +446,7 @@ def check_invalid(s): # No space around e. check_invalid("3.2 e1") check_invalid("3.2e 1") + check_invalid("232e\t2") # Fractional part don't need a sign. check_invalid("3.+2") check_invalid("3.-2") From 351fb766f0747015db8050ac46990dc84ffb2016 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 21:51:41 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst diff --git a/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst b/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst new file mode 100644 index 00000000000..b8c484d9eb9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst @@ -0,0 +1 @@ +Improve performance of construction of :class:`Fraction` from a string. From 983eb6aba1bb241f3c375e7c94efd1f99b27049d Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 4 May 2026 00:00:12 +0200 Subject: [PATCH 3/3] Apply suggestion from @eendebakpt --- .../next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst b/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst index b8c484d9eb9..13faa8ee440 100644 --- a/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst +++ b/Misc/NEWS.d/next/Library/2026-05-03-21-51-36.gh-issue-72902.TbChd6.rst @@ -1 +1 @@ -Improve performance of construction of :class:`Fraction` from a string. +Improve performance of construction of :class:`fractions.Fraction` from a string.