diff --git a/pep-0357.txt b/pep-0357.txt index 5d3004ab0..dc660cd38 100644 --- a/pep-0357.txt +++ b/pep-0357.txt @@ -28,9 +28,10 @@ Rationale In NumPy, for example, there are 8 different integer scalars corresponding to unsigned and signed integers of 8, 16, 32, and 64 bits. These type-objects could reasonably be used as integers in - many places where Python expects true integers. There should be - some way to be able to tell Python that an object can behave like - an integer. + many places where Python expects true integers but cannot inherit from + the Python integer type because of incompatible memory layouts. + There should be some way to be able to tell Python that an object can + behave like an integer. It is not possible to use the nb_int (and __int__ special method) for this purpose because that method is used to *coerce* objects @@ -45,15 +46,41 @@ Proposal Add an nb_index slot to PyNumberMethods, and a corresponding __index__ special method. Objects could define a function to place - in the nb_index slot that returns an appropriate C-integer for use - as ilow or ihigh in PySequence_GetSlice, PySequence_SetSlice, and - PySequence_DelSlice. This integer could also be used elsewhere by - Python when a C-integer is required. + in the nb_index slot that returns an appropriate C-integer (Py_ssize_t + after PEP 353). This C-integer will be used whenever Python needs + one such as in PySequence_GetSlice, PySequence_SetSlice, and + PySequence_DelSlice. +Specification: + + 1) The nb_index slot will have the signature + + Py_ssize_t index_func (PyObject *self) + + 2) The __index__ special method will have the signature + + def __index__(self): + return obj + + Where obj must be either an int or a long or another object that has the + __index__ special method (but not self). + + 3) A new C-API function PyNumber_Index will be added with signature + + Py_ssize_t PyNumber_index (PyObject *obj) + + which will special-case integer and long integer objects but otherwise + return obj->ob_type->tp_as_number->nb_index(obj) if it is available. + A -1 will be returned and an exception set on an error. + + 4) A new operator.index(obj) function will be added that calls + equivalent of obj.__index__() and raises an error if obj does not implement + the special method. + Implementation Plan 1) Add the nb_index slot in object.h and modify typeobject.c to - create the __index__ method. + create the __index__ method 2) Change the ISINT macro in ceval.c to ISINDEX and alter it to accomodate objects with the index slot defined. @@ -66,9 +93,10 @@ Implementation Plan check for the slot as well. 5) Add PyNumber_Index C-API to return an integer from any - Python Object that has the nb_index slot. + Python Object that has the nb_index slot. + + 6) Add the operator.index(x) function. - 6) Add an operator.index(x) function that calls x.__index__() Possible Concerns @@ -95,8 +123,16 @@ Possible Concerns interpretations of the slot are possible. For example, the slot can be used any time Python requires an integer internally (such as in "mystring" * 3). The name was suggested by Guido because - slicing syntax is the biggest reason for having such a slot and no - better name emerged. + slicing syntax is the biggest reason for having such a slot and + in the end no better name emerged. + + Why return Py_ssize_t from nb_index? + + The nb_index slot is primarily intended to return an integer + needed by the sequence interface. In Python 2.5 this is + Py_ssize_t. As this is the primary purpose of the slot, it + makes sense to return the C-integer directly and not wrapped + in a Python int object. Reference Implementation