[Python-Dev] Why does getitem slot of builtin call sequence methods first? (original) (raw)

Travis Oliphant oliphant at ee.byu.edu
Sun Oct 2 05:17:20 CEST 2005


Guido van Rossum wrote:

On 10/1/05, Travis Oliphant <oliphant at ee.byu.edu> wrote:

The new ndarray object of scipy core (successor to Numeric Python) is a C extension type that has a getitem defined in both the asmapping and the assequence structure. The assequence mapping is just so PySequenceGetItem will work correctly. As exposed to Python the ndarray object has a .getitem wrapper method. Why does this wrapper call the sequence getitem instead of the mapping getitem method? Is there anyway to get at a mapping-style getitem method from Python?

Hmm... I'm sure the answer is in typeobject.c, but that is one of the more obfuscated parts of Python's guts. I wrote it four years ago and since then I've apparently lost enough brain cells (or migrated them from language implementation to to language design service :) that I don't understand it inside out any more like I did while I was in the midst of it. However, I wonder if the logic isn't such that if you define both sqitem and mpsubscript, getitem calls sqitem; I wonder if by removing sqitem it might call mpsubscript? Worth a try, anyway.

Thanks for the tip. I think I figured out the problem, and it was my misunderstanding of how types inherit in C that was the source of my problem.

Basically, Python is doing what you would expect, the mp_item is used for getitem if both mp_item and sq_item are present. However, the addition of these descriptors (and therefore the resolution of any comptetion for getitem calls) is done before the inheritance of any slots takes place.

The new ndarray object inherits from a "big" array object that doesn't define the sequence and buffer protocols (which have the size limiting int dependencing in their interfaces). The ndarray object has standard tp_as_sequence and tp_as_buffer slots filled.

Figuring the array object would inherit its tp_as_mapping protocol from "big" array (which it does just fine), I did not explicitly set that slot in its Type object. Thus, when PyType_Ready was called on the ndarray object, the tp_as_mapping was NULL and so getitem mapped to the sequence-defined version. Later the tp_as_mapping slots were inherited but too late for getitem to be what I expected.

The easy fix was to initialize the tp_as_mapping slot before calling PyType_Ready. Hopefully, somebody else searching in the future for an answer to their problem will find this discussion useful.

Thanks for your help,

-Travis



More information about the Python-Dev mailing list