[Python-Dev] unsubscriptable vs object does not support indexing

Michael Foord fuzzyman at voidspace.org.uk
Wed Sep 23 23:19:00 CEST 2009


M.-A. Lemburg wrote:
> Brett Cannon wrote:
>   
>> On Tue, Sep 22, 2009 at 20:08, R. David Murray <rdmurray at bitdance.com> wrote:
>>     
>>> On Wed, 23 Sep 2009 at 02:01, MRAB wrote:
>>>       
>>>> Dino Viehland wrote:
>>>>         
>>>>>  Is there a reason or a rule by which CPython reports different error
>>>>>  message for different failures to subscript?
>>>>>
>>>>>  For example:
>>>>>
>>>>>           
>>>>>>>>  set()[2]
>>>>>>>>                 
>>>>>  Traceback (most recent call last):
>>>>>   File "<stdin>", line 1, in <module>
>>>>>  TypeError: 'set' object does not support indexing
>>>>>           
>>>>>>>>  class c(object): pass
>>>>>>>>                 
>>>>>  ...
>>>>>           
>>> [....]
>>>       
>>>>>>>>  [].append[42]
>>>>>>>>                 
>>>>>  Traceback (most recent call last):
>>>>>   File "<stdin>", line 1, in <module>
>>>>>  TypeError: 'builtin_function_or_method' object is unsubscriptable
>>>>>           
>>> [...]
>>>       
>>>>>  IronPython had a bug report that we were getting this wrong for set
>>>>>  objects and that “does not support indexing” was also a clearer error
>>>>>  message.  I’m wondering if there’s some reason why the different error
>>>>>  messages occur which I’m missing.   Otherwise I could switch to using
>>>>> the
>>>>>  more clear message or start marking types which should report the
>>>>>  unsubscriptable error.  Does anyone have any insights into this?
>>>>>
>>>>>           
>>>> I thought that the difference might be between iterable and non-iterable
>>>> objects, but then I'd expect the class 'c' to behave like the other
>>>> non-iterables. In fact, the result is different again if it's an
>>>> old-style class:
>>>>
>>>>         
>>>>>>>  class c: pass
>>>>>>>  c()[2]
>>>>>>>               
>>>> Traceback (most recent call last):
>>>>  File "<stdin>", line 1, in <module>
>>>>   c()[2]
>>>> AttributeError: c instance has no attribute '__getitem__'
>>>>         
>>> Looking at the source, these messages are generated from abstract.c, and
>>> the difference appears to be whether or not the tp_as_sequence slot is
>>> filled in or not.  If it is, but there is no sq_item method, then
>>> PySequence_GetItem gives the "does not support indexing" message.
>>> If it isn't filled in, you get the 'not subscriptable"(*) message from
>>> PyObject_GetItem.
>>>
>>> The logic appears to be, roughly, if an object does not have mapping
>>> methods, or has them but does not have mp_subscript, and does have
>>> sequence methods but does not have sq_item, then you get a 'does
>>> not support indexing'.  Otherwise you get 'not subscriptable'.
>>>
>>> The question is, is this a useful distinction, or is it an
>>> implementation artifact?
>>>       
>> Let's ignore history, which I bet is the reason for the distinction,
>> and just look at the error messages; does the distinction make sense
>> to a newbie? I would say no and that the "does not support indexing"
>> error message is more useful. For expert programmers they could figure
>> out the problem with either error message. The only help is if you are
>> trying to debug a type, but I am willing to bet most of us didn't know
>> the distinction at the C level until David looked it up.
>>
>> So I am +1 on unified the message and +1 on using the "does not
>> support indexing" one.
>>     
>
> +1 as well.
>   

Also +1. I had a friend (an experienced programmer) who started using 
Python recently. The cryptic nature of some of the error messages was a 
sore point with him.

Michael

> Note that the wording of error message has never been something
> we guaranteed backwards compatibility for, so such changes are a
> lot easier to implement than API changes.
>
> (I just hope that doctest doesn't rely on the message texts.)
>
>   


-- 
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/blog




More information about the Python-Dev mailing list