New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
__floordiv__ in module fraction fails with TypeError instead of returning NotImplemented #69598
Comments
__floordiv__ in module fraction fails with TypeError instead of returning NotImplemented when modulo is a class without __rtruediv__ or __mul__. Code sample: class Foo(object):
def __rdivmod__(self, other):
return 'rdivmod works'
from fractions import Fraction
a = Fraction(1,1)
b = Foo()
print(divmod(1, b))
print(divmod(a, b)) __divmod__ in Fraction is inherited from class Real (numbers.py): So __floordiv__ and __mod__ are called. def __floordiv__(a, b):
"""a // b"""
return math.floor(a / b)
def __mod__(a, b):
"""a % b"""
div = a // b
return a - b * div __floordiv__ if fractions.py makes a true division, and __mod__ makes multiplication. The following code will fix the problem: def __divmod__(self, other):
if isinstance(a, numbers.Complex):
return (self // other, self % other)
else:
return NotImplemented |
def __floordiv__(a, b):
"""a // b"""
if isinstance(b, numbers.Complex):
return math.floor(a / b)
else:
return NotImplemented And the same for __mod__. |
Can you please write a patch? See https://docs.python.org/devguide/ |
You should test the change with number types that don't use the number tower e.g. Decimal, sympy, gmpy2, mpf, numpy arrays etc. Few non stdlib types use the number ABCs so testing against numbers.Complex may cause a change in behaviour. |
OK, then we should not change numbers.py. And in fractions.py: def __floordiv__(a, b):
"""a // b"""
if isinstance(b, numbers.Complex) or hasattr(b, '__rtruediv__'):
fr = a / b
if fr != NotImplemented:
return math.floor(a / b)
else:
return NotImplemented
else:
return NotImplemented |
Bad idea, just def __floordiv__(a, b):
"""a // b"""
if isinstance(b, numbers.Complex):
return math.floor(a / b)
else:
return NotImplemented If b is inherited from number, real, complex, Fraction and etc, then a of type Fraction knows, how do make a division. |
... def reverse(b, a):
if isinstance(a, numbers.Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
return fallback_operator(float(a), float(b))
elif isinstance(a, numbers.Complex):
return fallback_operator(complex(a), complex(b))
else:
return NotImplemented
...
so division is possible only with int, Fraction, float, complex, numbers.Rational, numbers.Real, numbers.Complex.
For all of them "isinstance(b, numbers.Complex)" is true |
This patch actually fixes the problem: https://bugs.python.org/issue35588 from fractions import Fraction
import operator
class Goo:
__radd__, __rdivmod__, __rfloordiv__, __rmod__, __rmul__, __rpow__, __rsub__, __rtruediv__ = [lambda a, b: 'ok'] * 8 for func in operator.add, operator.sub, operator.mul, operator.truediv, operator.pow, operator.mod, operator.floordiv, divmod: |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: