This commit is contained in:
Pieter Eendebak 2026-05-03 22:00:15 +00:00 committed by GitHub
commit e1eed7d45c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 17 deletions

View file

@ -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<sign>[-+]?) # an optional sign, then
(?=\d|\.\d) # lookahead for digit or .digit
(?P<num>\d*|\d+(_\d+)*) # numerator (possibly empty)
(?: # followed by
(?:\s*/\s*(?P<denom>\d+(_\d+)*))? # an optional denominator
| # or
(?:\.(?P<decimal>\d*|\d+(_\d+)*))? # an optional fractional part
(?:E(?P<exp>[-+]?\d+(_\d+)*))? # and optional exponent
\A\s*+ # optional whitespace at the start,
(?P<sign>[-+]?+) # an optional sign, then
(?=\d|\.\d) # lookahead for digit or .digit
(?P<num>(?:\d++(?:_\d++)*+)?+) # numerator (possibly empty)
(?: # followed by
\s*+/\s*+(?P<denom>\d++(?:_\d++)*+) # a denominator
| # or
(?:\.(?P<decimal>(?:\d++(?:_\d++)*+)?+))?+ # an optional fractional part
(?:[eE](?P<exp>[-+]?+\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):

View file

@ -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")

View file

@ -0,0 +1 @@
Improve performance of construction of :class:`fractions.Fraction` from a string.