[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