[Python-Dev] int() and math.trunc don't accept objects that only define __index__

Rémi Lapeyre remi.lapeyre at henki.fr
Mon Feb 18 11:16:36 EST 2019


Hi, I open this thread to discuss the proposal by Nick Coghlan in
https://bugs.python.org/issue33039
to add __int__ and __trunc__ to a type when __index__ is defined.

Currently __int__ does not default to __index__ during class initialisation
so
both must be defined to get a coherant behavior:

    (cpython-venv) ➜  cpython git:(add-key-argument-to-bisect) ✗ python3
    Python 3.8.0a1+ (heads/add-key-argument-to-bisect:b7aaa1adad, Feb 18
2019, 16:10:22)
    [Clang 10.0.0 (clang-1000.10.44.4)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import math
    >>> class MyInt:
    ...     def __index__(self):
    ...             return 4
    ...
    >>> int(MyInt())
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: int() argument must be a string, a bytes-like object or a
number, not 'MyInt'
    >>> math.trunc(MyInt())
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: type MyInt doesn't define __trunc__ method
    >>> hex(MyInt())
    '0x4'
    >>> len("a"*MyInt())
    4
    >>> MyInt.__int__ = MyInt.__index__
    >>> int(MyInt())
    4


The difference in behavior is espacially weird in builtins like int() and
hex().


The documentation mentions at
https://docs.python.org/3/reference/datamodel.html#object.__index__
the need to always define both __index__ and __int__:

    Note: In order to have a coherent integer type class, when __index__()
is defined __int__() should also be defined, and both should return the
same value.

Nick Coghlan proposes to make __int__ defaults to __index__ when only the
second
is defined and asked to open a discussion on python-dev before making any
change
"as the closest equivalent we have to this right now is the "negative"
derivation,
where overriding __eq__ without overriding __hash__ implicitly marks the
derived
class as unhashable (look for "type->tp_hash =
PyObject_HashNotImplemented;").".


I think the change proposed makes more sense than the current behavior and
volunteer to implement it if it is accepted.


What do you think about this?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20190218/1c2faf82/attachment.html>


More information about the Python-Dev mailing list