bpo-40792: Make PyNumber_Index() always returning exact int.#20443
Conversation
| Return *a* converted to an integer. Equivalent to ``a.__index__()``. | ||
|
|
||
| .. versionchanged:: 3.10 | ||
| The type of the result is always :class:`int`. |
There was a problem hiding this comment.
It may be worth adding a sentence to explain how this is different from the previous behaviour, since I think it'll come as a surprise to many that this wasn't already true before.
There was a problem hiding this comment.
Could you please propose a wording? I have problems with formulating this in English.
There was a problem hiding this comment.
So maybe something like:
The result always has exact type :class:
int. Previously, the result could have been an instance of a subclass ofint.
| Py_off_t result; | ||
| PyObject *runerr; | ||
| PyObject *value = PyNumber_Index(item); | ||
| PyObject *value = _PyNumber_Index(item); |
There was a problem hiding this comment.
I'm missing something here: from my reading of the code, PyLong_AsOff_t is either PyLong_AsLong or PyLong_AsLongLong, and both of those already call _PyNumber_Index, so it looks as though we don't need this call.
Ah, I think I found what I'm missing: PyLong_AsOff_t could be PyLong_AsSsize_t, which doesn't call _PyNumber_Index. Is that right?
There was a problem hiding this comment.
Yes, it is right.
It a separate question whether PyLong_AsSsize_t and others should call __index__ implicitly. It is not simple question, because such change may introduce bugs by making presumably atomic code non-atomic.
There was a problem hiding this comment.
It a separate question whether
PyLong_AsSsize_tand others should call__index__implicitly.
Agreed. It seems worth looking into, but not in this PR.
There was a problem hiding this comment.
LGTM in principle. (Modulo failing CI tests.)
_PyNumber_Index does feel a bit like a premature optimization. Though since the optimization is already present in the original behaviour of PyNumber_Index, I suppose it would be better described as a delayed pessimization.
I suspect we don't have very many cases where an integer-expecting function needs to be fast when passed an instance of an integer subclass - there just aren't that many interesting integer subclasses around, besides bool. (NumPy no longer has any.) I'd probably discourage use of _PyNumber_Index in new code, for simplicity, but it makes sense to use it as a replacement for PyNumber_Index in existing code.
|
The "i" format unit is traditionally used to convert boolean arguments. Without such optimization we would need to create temporary integer objects 0 and 1 to convert boolean arguments. They are cached, but still. Other case is using IntEnum. Many integer constants in the stdlib are replaced with IntEnum, but they are parsed as integers in the C code. |
https://bugs.python.org/issue40792