In Python C API you cannot define a __getitem__ method; instead define a tp_as_mapping slot.  See:<div><br></div><div><a href="http://docs.python.org/c-api/typeobj.html#tp_as_mapping">http://docs.python.org/c-api/typeobj.html#tp_as_mapping</a></div>
<div><br><br><div class="gmail_quote">2009/12/23 Anita A <span dir="ltr">&lt;<a href="mailto:anitaa1981@gmail.com">anitaa1981@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi all,<br>
<br>
I am trying to implement a subscriptable type in c++ (equivalent to python<br>
dict), but I get a &#39;type is unsubscriptable&#39; error. Here is a minimal<br>
code sample I tried:<br>
<br>
--------------------------------------------------------------------------<br>
#include &lt;Python.h&gt;<br>
#include &lt;iostream&gt;<br>
#include &quot;pyerror.hpp&quot;<br>
<br>
/////////////////////////////////////////////////////////<br>
PyObject* getitem(PyObject* self, PyObject* args)<br>
{<br>
    std::cout &lt;&lt; &quot;getitem&quot; &lt;&lt; std::endl;<br>
    return PyString_FromString(&quot;this is an item&quot;);<br>
}<br>
<br>
PyMethodDef method[] = {<br>
     {&quot;__getitem__&quot;, &amp;getitem, METH_VARARGS, &quot;&quot;},<br>
     {0, 0, 0, 0}<br>
};<br>
<br>
static PyMethodDef module_methods[] = {<br>
     { 0, 0, 0, 0 }<br>
};<br>
<br>
struct MyObject<br>
{<br>
    PyObject_HEAD<br>
};<br>
<br>
extern const char* code;<br>
<br>
int main(int argc, char *argv[])<br>
{<br>
    Py_InitializeEx(0);<br>
<br>
    PyObject* myModule = Py_InitModule3(&quot;test&quot;, module_methods, &quot;test module&quot;);<br>
    assert(myModule);<br>
<br>
    PyTypeObject myType;<br>
    memset(&amp;myType, 0, sizeof(PyTypeObject));<br>
<br>
    myType.tp_name = &quot;myType&quot;;<br>
    myType.tp_basicsize = sizeof(MyObject);<br>
    myType.tp_methods = method;<br>
    if (PyType_Ready(&amp;myType) &lt; 0)<br>
    {<br>
        std::cout &lt;&lt; &quot;type error&quot; &lt;&lt; std::endl;<br>
        return 1;<br>
    }<br>
<br>
    PyModule_AddObject(myModule, myType.tp_name, (PyObject*)&amp;myType);<br>
<br>
    PyObject* m = PyImport_AddModule(&quot;__main__&quot;);<br>
    PyObject* d = PyModule_GetDict(m);<br>
    MyObject* odef = PyObject_New(MyObject, &amp;myType);<br>
    PyDict_SetItemString(d, &quot;obj&quot;, (PyObject*)odef);<br>
<br>
    PyObject* rv = PyRun_String(code, Py_file_input, d, d);<br>
    if(rv == 0)<br>
    {<br>
        std::cout &lt;&lt; &quot;run error&quot; &lt;&lt; std::endl;<br>
        printException();<br>
        return 1;<br>
    }<br>
<br>
    Py_Finalize();<br>
    std::cout &lt;&lt; &quot;Done.\n&quot;;<br>
<br>
    return 0;<br>
}<br>
<br>
const char* code =<br>
&quot;print dir(obj)\n&quot;<br>
&quot;x = obj.__getitem__(1)\n&quot;<br>
&quot;print &#39;direct call:&#39;, x\n&quot;<br>
&quot;x = obj[1]\n&quot;<br>
;<br>
<br>
--------------------------------------------------------------------------<br>
Compile and run session.<br>
--------------------------------------------------------------------------<br>
$ g++ -I/usr/include/python2.6 pymin.cpp -lpython2.6<br>
$ ./a.out<br>
[&#39;__class__&#39;, &#39;__delattr__&#39;, &#39;__doc__&#39;, &#39;__format__&#39;,<br>
&#39;__getattribute__&#39;, &#39;__getitem__&#39;, &#39;__hash__&#39;, &#39;__init__&#39;, &#39;__new__&#39;,<br>
&#39;__reduce__&#39;, &#39;__reduce_ex__&#39;, &#39;__repr__&#39;, &#39;__setattr__&#39;,<br>
&#39;__sizeof__&#39;, &#39;__str__&#39;, &#39;__subclasshook__&#39;]<br>
getitem<br>
direct call: this is an item<br>
run error<br>
Error in execution:<br>
Traceback (most recent call last):<br>
line 4, in ??<br>
&lt;type &#39;exceptions.TypeError&#39;&gt;: &#39;myType&#39; object is unsubscriptable<br>
--------------------------------------------------------------------------<br>
<br>
As you can see, when I call __getitem__() directly, it works, but when I<br>
call it as a subscriptable object, I get an error. What am I missing?<br>
<br>
A simple python equivalent class works as expected:<br>
--------------------------------------------------------------------------<br>
class Testi:<br>
    def __getitem__(self, idx):<br>
        return 10<br>
<br>
if __name__ == &#39;__main__&#39;:<br>
    x = Testi()<br>
    print dir(x)<br>
    print x[&#39;a&#39;]<br>
--------------------------------------------------------------------------<br>
Run session.<br>
--------------------------------------------------------------------------<br>
$ python tst.py<br>
[&#39;__doc__&#39;, &#39;__getitem__&#39;, &#39;__module__&#39;]<br>
10<br>
--------------------------------------------------------------------------<br>
<br>
I had tried using the PyMappingMethods structure as documented, but there<br>
is apparently no way to implement the __contains__() method, that is, to<br>
check if a key is present in the dict.<br>
<br>
Any help would be appreciated.<br>
_______________________________________________<br>
Cplusplus-sig mailing list<br>
<a href="mailto:Cplusplus-sig@python.org">Cplusplus-sig@python.org</a><br>
<a href="http://mail.python.org/mailman/listinfo/cplusplus-sig" target="_blank">http://mail.python.org/mailman/listinfo/cplusplus-sig</a><br>
</blockquote></div><br><br clear="all"><br>-- <br>Gustavo J. A. M. Carneiro<br>INESC Porto, Telecommunications and Multimedia Unit<br>&quot;The universe is always one step beyond logic.&quot; -- Frank Herbert<br>
</div>