Deprecate delegation of int to __trunc__ #89140
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
assignee = None closed_at = <Date 2022-02-03.09:44:44.771> created_at = <Date 2021-08-22.09:17:57.051> labels = ['interpreter-core', '3.11'] title = 'Deprecate delegation of int to __trunc__' updated_at = <Date 2022-02-03.09:44:44.770> user = 'https://github.com/mdickinson'
activity = <Date 2022-02-03.09:44:44.770> actor = 'serhiy.storchaka' assignee = 'none' closed = True closed_date = <Date 2022-02-03.09:44:44.771> closer = 'serhiy.storchaka' components = ['Interpreter Core'] creation = <Date 2021-08-22.09:17:57.051> creator = 'mark.dickinson' dependencies =  files =  hgrepos =  issue_num = 44977 keywords = ['patch'] message_count = 12.0 messages = ['400063', '400064', '400073', '400074', '400076', '400078', '400079', '400080', '400082', '412190', '412431', '412432'] nosy_count = 4.0 nosy_names = ['rhettinger', 'mark.dickinson', 'serhiy.storchaka', 'ZackerySpytz'] pr_nums = ['31031'] priority = 'normal' resolution = 'fixed' stage = 'resolved' status = 'closed' superseder = None type = None url = 'https://bugs.python.org/issue44977' versions = ['Python 3.11']
The text was updated successfully, but these errors were encountered:
The int constructor, when applied to a general Python object
The delegation to __trunc__ used to be useful: it meant that users could write a custom class SomeNumber with the property that:
class SomeNumber: def __trunc__(self): <return truncated value for self>
However, with Python >= 3.10, we no longer use __int__ implicitly for argument conversion in internal code. So the second point above is no longer a concern, and SomeNumber can now simply be written as
class SomeNumber: def __int__(self): <return truncated value for self>
This decouples int from __trunc__ and leaves __trunc__ as simply the support for the math.trunc function.
Argh; copy and paste fail - I left out the crucial line.
I propose deprecating the delegation of int to __trunc__: calls to int(a) where type(a) implements __trunc__ but not __int__ or __index__ would raise a DeprecationWarning, and at some point in the future int(a) would become a TypeError.
A GitHub code search shows a substantial number of uses of math.trunc out in the wild:
So unfortunately, getting rid of math.trunc and __trunc__ looks a bit too much as though it would cause gratuitous breakage.
I think the needs are sufficiently different that __trunc__ still has value as its own thing, and it's a natural counterpart to __floor__ and __ceil__ (out of all the directed rounding modes, rounding towards zero probably turns up more often than rounding towards +inf or -inf).
__int__ has the disadvantage that it must return an int, so it's not useful for other Python-based numeric systems with their own rational number / integer pairing. For example, with gmpy2, truncating an mpq instance returns an mpz instance, which is what I'd expect and want - if I'm working with huge values then it would be annoying for math.trunc to do the inefficient thing and return a plain int.
>>> from gmpy2 import mpq >>> math.trunc(mpq(22, 7)) mpz(3)
SymPy behaves similarly:
>>> from sympy import Rational >>> type(math.trunc(Rational(22, 7))) <class 'sympy.core.numbers.Integer'>
On the other side, there are conversions to integer that it doesn't make sense to think of as truncation. It would be odd for a UUID to be a valid input to math.trunc, for example:
>>> int(uuid.uuid4()) 43341414945793370480422623795805641537