Author barry
Recipients barry, docs@python
Date 2013-03-29.22:25:10
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
operator.index() is just a thin wrapper around PyNumber_Index().  The documentation for operator.index() claims that it is equivalent to calling obj.__index__() but for subclasses of int, this is not true.  In fact, PyNumber_Index() first does (e.g. in Python 3.3) a PyLong_Check() and if that succeeds, the original object is returned *without* doing the moral equivalent in C of calling obj.__index__().  An example:

class myint(int):
    def __index__(self):
        return int(self) + 1

>>> x = myint(7)
>>> x.__index__()
>>> from operator import index
>>> index(x)

The C API documents PyNumber_Index() as: "Returns the o converted to a Python int on success or NULL with a TypeError exception raised on failure."

Because this has been the behavior of PyNumber_Index() since at least 2.7 (I didn't check farther back), this probably cannot be classified as a bug deserving to be fixed in the code for older Pythons.  It might be worth fixing for Python 3.4, i.e. by moving the index check before the type check.  In the meantime, this is probably a documentation bug.

The C API implies, but should be clearer that if o is an int subtype (int and long in Python 2), it is returned unchanged.  The operator.index() documentation should be amended to describe this behavior for int/long subclasses.

A different alternative would be to leave PyNumber_Index() unchanged, but with the doco fix, and to augment operator.index() to do the PyIndex_Check() first, before calling PyNumber_Index().  That's a little more redundant, but would provide the documented behavior without changing the C API.
Date User Action Args
2013-03-29 22:25:11barrysetrecipients: + barry, docs@python
2013-03-29 22:25:11barrysetmessageid: <>
2013-03-29 22:25:11barrylinkissue17576 messages
2013-03-29 22:25:10barrycreate