Author rhettinger
Recipients barry, eric.smith, eric.snow, llllllllll, rhettinger
Date 2015-04-26.23:04:43
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1430089483.51.0.982412630927.issue23910@psf.upfronthosting.co.za>
In-reply-to
Content
One other thought: the itemgetter.__call__ method is already pretty thin:

    if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
	return NULL;
    if (nitems == 1)
        return PyObject_GetItem(obj, ig->item);

But you could add a special case for single integer index being applied to a known sequence.  Extract the Py_ssize_t index in itemgetter_new and store it in the itemgetterobject.  Then add a fast path in itemgetter.__call__.  Roughly something like this:

  if (ig->index != -1 &&
      PyTuple_Check(obj) && 
      nitems == 1 &&
      PyTuple_GET_SIZE(obj) > ig->index) {
       result = PySequence_Fast_GET_ITEM(obj, ig->index);
       Py_INCREF(result);
       return result;
  }
 
Perhaps also add a check to make sure the tuple subclass hasn't overridden the __getitem__ method (see an example of how to do this in the code for Modules/_collectionsmodule.c::_count_elements()).

Something along these lines would allow all the steps to be inlined and would eliminate all the usual indirections inherent in the abstract API.

Another alternative is to use the PySequence API instead of the PyTuple API.  That trades away a little of the speed-up in return for speeding-up itemgetter on lists as well as tuples.
History
Date User Action Args
2015-04-26 23:04:43rhettingersetrecipients: + rhettinger, barry, eric.smith, eric.snow, llllllllll
2015-04-26 23:04:43rhettingersetmessageid: <1430089483.51.0.982412630927.issue23910@psf.upfronthosting.co.za>
2015-04-26 23:04:43rhettingerlinkissue23910 messages
2015-04-26 23:04:43rhettingercreate