[issue17576] PyNumber_Index() is not int-subclass friendly (or operator.index() docos lie)

Mark Dickinson report at bugs.python.org
Thu May 28 04:41:58 EDT 2020


Mark Dickinson <dickinsm at gmail.com> added the comment:

[Serhiy]

> * Undeprecate accepting __index__ and __int__ returning instances of int sublasses. There is no difference from the side of using int and index(), but it can simplify user implementations of __index__ and __int__.

I'm not sure about this. Thinking about the bigger picture, we have a similar deprecation in place for __float__ returning an instance of a float subclass. That one I'd like to keep (and probably make an error for 3.10).

A problem I've run into in Real Code (TM) is needing to convert something float-like to a float, using the same mechanisms that (for example) something like `math.sqrt` uses.

One option is to call "float", but that requires explicitly excluding str, bytes and bytearray, which feels ugly and not very future-proof.

So the code ends up calling __float__. But because __float__ can return an instance of a float subclass, it then still needs some way to convert the return value to an actual float. And that's surprisingly tricky.

So I really *do* want to see the ability of __float__ to return a non-float eventually removed.

Similarly for __int__, there's no easy Python-side way to mimic the effect of calling __int__, followed by converting to an exact int. We have to:

1. Do an explicit check for non-numbers (str, bytes, bytearray)
2. Call int

Or:

1. Call __int__
2. Convert an instance of a possible subclass of int to something of exact type int. I don't know how to do this cleanly in general in Python, and end up resorting to evil tricks like adding `0`.

Deprecating allowing __int__ to return a non-int helps here, because it lets me simply call __int__.

I care much more about the __float__ case than the __int__ case, because the "right way" to duck-type integers is to use __index__ rather than __int__, and for __index__ we have operator.index as a solution.

But it would seem odd to have the rule in place for __float__ but not for __int__ and __index__.


The other way to solve my problem would be to provide an operator module function (operator.as_float?) that does a duck-typed conversion of an arbitrary Python object to a float.

----------
nosy: +mark.dickinson

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue17576>
_______________________________________


More information about the Python-bugs-list mailing list