unsubscriptable vs object does not support indexing
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 ... c()[2] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'c' object does not support indexing
But compare this to:
[].append[42] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'builtin_function_or_method' object is unsubscriptable (lambda: 42)[42] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'function' object is unsubscriptable property()[42] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'property' 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?
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
...
c()[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'c' object does not support indexing
But compare this to:
[].append[42]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'builtin_function_or_method' object is unsubscriptable
(lambda: 42)[42]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'function' object is unsubscriptable
property()[42]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'property' 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__'
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? --David (*) The error message changed format slightly in 2.7 due to http://bugs.python.org/issue5760, and the discussion there is worth reading in this context.
R. David Murray wrote:
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?
First on the useful distinction: for better or worse users do seem to have an affinity towards CPython's error messages and especially so when they're better than ours :). But I certainly hope no one is taking a dependency on them by parsing them or anything like that such that it would actually break someone's program. So basically I regard all error messages as implementation artifacts but I have no problem matching them if it'll make someone happier and it's not too crazy to do it. That being said there does seem to be a useful distinction here. It sounds like the idea here is to report a better error message when something is more collection like than a full blown sequence - in particular I'm thinking of .NET's ICollection and Java's Collection interfaces that are very sequence like but don't support getting elements by index. The only oddity in the error message to me is that user defined objects are effectively always treated as sequences. That's completely an implementation artifact but I'm going to copy it too because it's easy, may prevent another bug report, and checking for all the various sequence methods seems like unnecessary overkill. Thanks for the information!
On Tue, Sep 22, 2009 at 20:08, R. David Murray <rdmurray@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. -Brett
Brett wrote:
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.
I'd be +1 on the unified message as well - but it seems what that message should be may be contentious (and quite a bike shed discussion at that). The bug David linked to (http://bugs.python.org/issue5760) has a preference for subscript because that's what's used elsewhere in the language.
On Wed, Sep 23, 2009 at 13:47, Dino Viehland <dinov@microsoft.com> wrote:
Brett wrote:
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.
I'd be +1 on the unified message as well - but it seems what that message should be may be contentious (and quite a bike shed discussion at that). The bug David linked to (http://bugs.python.org/issue5760) has a preference for subscript because that's what's used elsewhere in the language.
That's what's used in the language spec which VERY few people read. That can use more technical jargon, but I still don't see experienced programmers having issuesvfiguring out that note being able to index an object is the same as not being subscriptable. And we can change the docs as well if needed, but I don't think that is necessary. -Brett
On Thu, 24 Sep 2009 06:47:41 am Dino Viehland wrote:
So I am +1 on unified the message and +1 on using the "does not support indexing" one.
I'd be +1 on the unified message as well - but it seems what that message should be may be contentious (and quite a bike shed discussion at that). The bug David linked to (http://bugs.python.org/issue5760) has a preference for subscript because that's what's used elsewhere in the language.
For what it's worth, "unsubscriptable object" seems to me to be mysterious to many newbies, and even a few non-newbies. It took me something like seven years of coding to stop reading it as "unscriptable object", and I'm sure I won't be the only one. As far as I can see, in practice, people talk about obj[i] as the item at index i, not the item at subscript i -- the term "subscript" in this context seems to be rare to non-existent except for the error message. -- Steven D'Aprano
Steven D'Aprano wrote:
On Thu, 24 Sep 2009 06:47:41 am Dino Viehland wrote:
So I am +1 on unified the message and +1 on using the "does not support indexing" one. I'd be +1 on the unified message as well - but it seems what that message should be may be contentious (and quite a bike shed discussion at that). The bug David linked to (http://bugs.python.org/issue5760) has a preference for subscript because that's what's used elsewhere in the language.
For what it's worth, "unsubscriptable object" seems to me to be mysterious to many newbies, and even a few non-newbies. It took me something like seven years of coding to stop reading it as "unscriptable object", and I'm sure I won't be the only one.
As far as I can see, in practice, people talk about obj[i] as the item at index i, not the item at subscript i -- the term "subscript" in this context seems to be rare to non-existent except for the error message.
How about if it's obj["item"]? To me the following makes complete sense, but then it seems that I may just be the odd one out.
class A(object): ... pass ... a = A() a[1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'A' object is unindexable a["a"] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'A' object is unsubscriptable
Janzert
Janzert wrote:
Steven D'Aprano wrote:
On Thu, 24 Sep 2009 06:47:41 am Dino Viehland wrote:
So I am +1 on unified the message and +1 on using the "does not support indexing" one. I'd be +1 on the unified message as well - but it seems what that message should be may be contentious (and quite a bike shed discussion at that). The bug David linked to (http://bugs.python.org/issue5760) has a preference for subscript because that's what's used elsewhere in the language. For what it's worth, "unsubscriptable object" seems to me to be mysterious to many newbies, and even a few non-newbies. It took me something like seven years of coding to stop reading it as "unscriptable object", and I'm sure I won't be the only one.
As far as I can see, in practice, people talk about obj[i] as the item at index i, not the item at subscript i -- the term "subscript" in this context seems to be rare to non-existent except for the error message.
How about if it's obj["item"]? To me the following makes complete sense, but then it seems that I may just be the odd one out.
class A(object): ... pass ... a = A() a[1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'A' object is unindexable a["a"] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'A' object is unsubscriptable
I prefer "index" to "subscript" and "does not support foo" or "cannot be fooed" to "is unfooable" (because, to me, "not" is more explicit than "un-"). I also prefer the same term to be used irrespective of the value used.
Steven D'Aprano <steve@pearwood.info> writes:
As far as I can see, in practice, people talk about obj[i] as the item at index i, not the item at subscript i -- the term "subscript" in this context seems to be rare to non-existent except for the error message.
Presumably, the same people would also call ‘obj[i]’ the item at *key* ‘i’, if ‘obj’ is a dictionary. For an object that supports neither indexes nor keys, though, how is Python to know which the user meant? It's a single operation as far as the parser is concerned, so there needs to be a single term for it. That term is “subscript”. Your point about the awkward word “unsubscriptable” is well-taken, though. Perhaps a simple improvement to the message wording: >>> foo = 3 >>> foo[6] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object does not support subscripts >>> foo['spam'] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object does not support subscripts -- \ “I lost a button-hole.” —Steven Wright | `\ | _o__) | Ben Finney
Ben Finney wrote:
Steven D'Aprano <steve@pearwood.info> writes:
As far as I can see, in practice, people talk about obj[i] as the item at index i, not the item at subscript i -- the term "subscript" in this context seems to be rare to non-existent except for the error message.
Presumably, the same people would also call ‘obj[i]’ the item at *key* ‘i’, if ‘obj’ is a dictionary. For an object that supports neither indexes nor keys, though, how is Python to know which the user meant? It's a single operation as far as the parser is concerned, so there needs to be a single term for it. That term is “subscript”.
Your point about the awkward word “unsubscriptable” is well-taken, though. Perhaps a simple improvement to the message wording:
>>> foo = 3 >>> foo[6] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object does not support subscripts >>> foo['spam'] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object does not support subscripts
It's called a 'subscript' because conventional mathematical notation uses subscripting. Newbies might be acquainted with the term 'index' from books, where the 'value' is non-numeric. It's a bit unfortunate that dicts have keys+value instead of index+value! :-)
MRAB <python <at> mrabarnett.plus.com> writes:
It's called a 'subscript' because conventional mathematical notation uses subscripting. Newbies might be acquainted with the term 'index' from books, where the 'value' is non-numeric. It's a bit unfortunate that dicts have keys+value instead of index+value!
Well, "index" for me points to the mathematical notion of an index, which AFAIK is always numeric. So it would be a mistake to use that term for dicts. Regards Antoine.
On Wed, Sep 23, 2009 at 5:25 PM, Antoine Pitrou <solipsis@pitrou.net> wrote:
MRAB <python <at> mrabarnett.plus.com> writes:
It's called a 'subscript' because conventional mathematical notation uses subscripting. Newbies might be acquainted with the term 'index' from books, where the 'value' is non-numeric. It's a bit unfortunate that dicts have keys+value instead of index+value!
Well, "index" for me points to the mathematical notion of an index, which AFAIK is always numeric. So it would be a mistake to use that term for dicts.
'Key' and 'index' refer to semantics. 'Subscript' refers to syntax. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Ben Finney wrote:
It's a single operation as far as the parser is concerned, so there needs to be a single term for it. That term is “subscript”.
How about something like "does not support the [] operation". This refers directly to the syntax involved, rather than using a typographical term that is at best a metaphor when applied to a language written linearly. -- Greg
Brett Cannon wrote:
On Tue, Sep 22, 2009 at 20:08, R. David Murray <rdmurray@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. 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.) -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Sep 23 2009)
Python/Zope Consulting and Support ... http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/
M.-A. Lemburg wrote:
Brett Cannon wrote:
On Tue, Sep 22, 2009 at 20:08, R. David Murray <rdmurray@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
On Wed, Sep 23, 2009 at 14:19, Michael Foord <fuzzyman@voidspace.org.uk> wrote: [SNIP]
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.
Do you know which error messages? We can change them. We have always said that we view exception messages as something that can change in minor releases and that you should be very careful if you ever use them in tests. -Brett
Brett Cannon wrote:
On Wed, Sep 23, 2009 at 14:19, Michael Foord <fuzzyman@voidspace.org.uk> wrote: [SNIP]
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.
Do you know which error messages? We can change them. We have always said that we view exception messages as something that can change in minor releases and that you should be very careful if you ever use them in tests.
There were a couple and I can only remember the last one he talked about. He ran some code with "python -3" that used someone else's library and resulted in the following warning, that he felt was cryptic: DeprecationWarning: Overriding __eq__ blocks inheritance of __hash__ in 3.x Hmm... not entirely sure how we can make it clearer. There is a great blog entry on the subject by Eric Lippert though (Microsoft I'm afraid): http://blogs.msdn.com/ericlippert/archive/2006/07/07/659259.aspx Error messages: diagnostic is preferable to prescriptive * Polite: making the user feel like an idiot is very, very bad. * Readable: poor grammar and tortured sentence structure is bad. * Accurate: error messages must accurately describe the problem. * Precise: "Something is wrong" is an accurate error message but not a very precise one! * Diagnostic but not prescriptive: describe the problem, not the solution. How about (?): If you implement equality (__eq__) you should also implement hashing (__hash__), it won't be inherited in 3.x. Although that is prescriptive of course... Michael
-Brett
-- http://www.ironpythoninaction.com/ http://www.voidspace.org.uk/blog
On Wed, Sep 23, 2009 at 14:49, Michael Foord <fuzzyman@voidspace.org.uk> wrote:
Brett Cannon wrote:
On Wed, Sep 23, 2009 at 14:19, Michael Foord <fuzzyman@voidspace.org.uk> wrote: [SNIP]
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.
Do you know which error messages? We can change them. We have always said that we view exception messages as something that can change in minor releases and that you should be very careful if you ever use them in tests.
There were a couple and I can only remember the last one he talked about. He ran some code with "python -3" that used someone else's library and resulted in the following warning, that he felt was cryptic:
DeprecationWarning: Overriding __eq__ blocks inheritance of __hash__ in 3.x
Hmm... not entirely sure how we can make it clearer. There is a great blog entry on the subject by Eric Lippert though (Microsoft I'm afraid):
http://blogs.msdn.com/ericlippert/archive/2006/07/07/659259.aspx
Error messages: diagnostic is preferable to prescriptive
* Polite: making the user feel like an idiot is very, very bad. * Readable: poor grammar and tortured sentence structure is bad. * Accurate: error messages must accurately describe the problem. * Precise: "Something is wrong" is an accurate error message but not a very precise one! * Diagnostic but not prescriptive: describe the problem, not the solution.
How about (?):
If you implement equality (__eq__) you should also implement hashing (__hash__), it won't be inherited in 3.x.
Although that is prescriptive of course...
So the original makes sense if you are implementing an object's comparison operator. But if you are not it won't make much sense, although if you are not implementing it then it shouldn't be your concern. Then again, if you are trying to upgrade your code and some library you used has not, I can see how that message would throw you for a loop. So +0 on your specific improvment and +1 for trying to think about newbies when writing exception messages. -Brett
Brett Cannon wrote:
So +0 on your specific improvment and +1 for trying to think about newbies when writing exception messages.
The __eq__/__hash__ messages are somewhat arcane because the problem they're describing is somewhat arcane. Michael's suggested improvement also isn't quite right (and I believe indicates that we're susceptible to issuing false alarms in this case). You really only need to override __hash__ if you want your object to remain hashable, but we currently issue the warning for any object that defines __eq__ without defining __hash__. Perhaps the implementation of that warning should be improved so that it is only issued if the default __hash__ implementation is actually invoked on an affected object? (the downside is that depending on the implementation technique the extra checks may slow down hashing under "python -3", but I guess that kind of the undesirable impact is the reason we have all those warnings switched off by default) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
participants (13)
-
Antoine Pitrou
-
Ben Finney
-
Brett Cannon
-
Dino Viehland
-
Greg Ewing
-
Guido van Rossum
-
Janzert
-
M.-A. Lemburg
-
Michael Foord
-
MRAB
-
Nick Coghlan
-
R. David Murray
-
Steven D'Aprano