Add a special TypeError subclass for implementation errors
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols. For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error). User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code. Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
Serhiy Storchaka wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols. For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
what's the reason for this not to raise AttributeError? I assume you asked this question in relation to the 3.11 changes to `with x:` raising TypeError vs AttributeError ?
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code. Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think ProtocolError would be too easily confused as relating to typing.Protocol or asyncio.Protocol ImplementationError sounds like it's related to `abc`s or NotImplementedError How about `AttributeNotFoundError` or `AttributeRequiredError` ?
03.09.21 10:34, Thomas Grainger пише:
what's the reason for this not to raise AttributeError?
At least backward compatibility. Currently a TypeError is raised in such cases, and AttributeError is not a subtype of TypeError. Also, not always any attribute is involved. For example, float() raises a TypeError if __float__() returns not float. And even if some dunder name is involved, rules for resolving special methods and common attributes are different.
I assume you asked this question in relation to the 3.11 changes to `with x:` raising TypeError vs AttributeError ?
No, it is not related. It was a bug to raise AttributeError, now it is fixed, but the fix is not backported for compatibility reasons.
How about `AttributeNotFoundError` or `AttributeRequiredError` ?
It would be confused with completely unrelated AttributeError.
03.09.21 10:34, Thomas Grainger пише:
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
I agree that TypeErrors raised for incorrect number or names of arguments is a separate class of TypeErrors. But it is not related to my proposition. It includes also two kinds of errors: 1. Programming error. The author of the calling code uses a known function improperly or the author of the function break compatibility. 2. User input error. If a user provides an incompatible callable.
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better. -- Oscar
The question is, would anyone ever want to make a distinction between the two in *real* code? I find it unlikely that someone would write try: sum(x, y, z) except TypeError: ... If you bury the sum() call deep inside other code, I'd say your try/except net is too wide. On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation
error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
-- Oscar _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3CLXFC... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On Fri, Sep 3, 2021 at 9:35 AM Guido van Rossum <guido@python.org> wrote:
The question is, would anyone ever want to make a distinction between the two in *real* code?
I expect not. However, finer grained exception may help with debugging and testing. -CHB find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
If you bury the sum() call deep inside other code, I'd say your try/except net is too wide.
On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation
error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
-- Oscar _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3CLXFC... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/> _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MXVBSN... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
But the text of the error message will explain all you need for debugging and testing. On Fri, Sep 3, 2021 at 10:08 AM Christopher Barker <pythonchb@gmail.com> wrote:
On Fri, Sep 3, 2021 at 9:35 AM Guido van Rossum <guido@python.org> wrote:
The question is, would anyone ever want to make a distinction between the two in *real* code?
I expect not.
However, finer grained exception may help with debugging and testing.
-CHB
find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
If you bury the sum() call deep inside other code, I'd say your try/except net is too wide.
On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer
error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is
(implementation the
same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
-- Oscar _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3CLXFC... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/> _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MXVBSN... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris)
Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On Fri, Sep 3, 2021 at 1:13 PM Guido van Rossum <guido@python.org> wrote:
But the text of the error message will explain all you need for debugging and testing.
debugging, probably yes. But it's a lot easier to check that a particular Exception is raised than to have to check for the Exception and also parse the error message. Honestly, I haven't figured out a use case for this particular example, but I do appreciate finer grained Exceptions in general. -CHB However, finer grained exception may help with debugging and testing.
-CHB
find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
If you bury the sum() call deep inside other code, I'd say your try/except net is too wide.
On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin < oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer
error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is
(implementation the
same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
> sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
-- Oscar _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3CLXFC... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/> _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MXVBSN... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris)
Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Fri, Sep 3, 2021 at 5:37 PM Christopher Barker <pythonchb@gmail.com> wrote:
On Fri, Sep 3, 2021 at 1:13 PM Guido van Rossum <guido@python.org> wrote:
But the text of the error message will explain all you need for debugging and testing.
debugging, probably yes.
But it's a lot easier to check that a particular Exception is raised than to have to check for the Exception and also parse the error message.
Honestly, I haven't figured out a use case for this particular example, but I do appreciate finer grained Exceptions in general.
Hm. More is not always better. (Today's entry for the 20th "Zen of Python" line. :-) -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On 4/09/21 4:32 am, Guido van Rossum wrote:
The question is, would anyone ever want to make a distinction between the two in *real* code?
Another problem with this idea is that there isn't just one user and one author. Library code often calls other library code written by a different author, so a user error at one level is an implementation error at another. -- Greg
On Fri, 3 Sept 2021 at 17:32, Guido van Rossum <guido@python.org> wrote:
On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer (implementation error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is the same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
The question is, would anyone ever want to make a distinction between the two in *real* code? I find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
If you bury the sum() call deep inside other code, I'd say your try/except net is too wide.
You've misunderstood. I do *not* want to catch the exception from sum(x, y, z). Sometimes a situation arises that there is a problem involving an exception being raised that is best fixed by catching the exception. Python does not provide much of a programmatic API for inspecting exceptions beyond simply choosing which class of exceptions to catch. That makes it important to limit the class of exceptions caught as carefully as possible. If the exception that needs to be caught is literally TypeError then it is not possible to be more precise than simply "except TypeError". I have seen code that parses the error messages but that seems flakey to me. The problem with "except TypeError" is that it also catches exceptions from situations where the exception should very rarely be caught e.g. sum(1, 2, 3). If the different cases that currently result in TypeError were broken down into more fine-grained exception classes then I think that would be good. A similar thing happened for OSError - in that case it was previously possible to distinguish cases using the errno attribute but it was awkward. In the case of TypeError there is nothing akin to the errno attribute so you either catch all TypeError or none. -- Oscar
On Fri, Sep 3, 2021 at 5:04 PM Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On Fri, 3 Sept 2021 at 17:32, Guido van Rossum <guido@python.org> wrote:
On Fri, Sep 3, 2021 at 4:24 AM Oscar Benjamin <
On Fri, 3 Sept 2021 at 08:10, Serhiy Storchaka <storchaka@gmail.com>
wrote:
There are two different kinds of TypeError: if the end user passes an instance of wrong type and if the author of the library makes an error in implementation of some protocols.
For example, len(obj) raises TypeError in two cases: if obj does not have __len__ (user error) and if obj.returns non-integer
(implementation
error). for x in obj raises TypeError if obj does not have __iter__ (user error) and if iter(obj) does not have __next__ (implementation error).
User errors can be fixed on user side, implementation errors can only be fixed by the author of the class. Even if the user and the author is
same person, these errors point to different places of code.
Would it be worth to add a special TypeError subclass for implementation errors to distinguish them from user errors? How to name it (ImplementationError, ProtocolError, etc)?
I think that it would be good to make TypeError more fine-grained. Another example is:
sum(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sum() takes at most 2 arguments (3 given)
There can be reasons in library code to catch TypeError that might arise from bad user input but in those situations you would usually not want to catch this TypeError. The error from calling a function with the wrong number of arguments would usually mean a bug in the library code which should not be caught. Conversely if the user input is a callable and you do want to catch the error resulting from it being called with the wrong number of arguments then catching TypeError is too broad again. Something like BadArgumentsError would be better.
The question is, would anyone ever want to make a distinction between
oscar.j.benjamin@gmail.com> wrote: the the two in *real* code? I find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
If you bury the sum() call deep inside other code, I'd say your
try/except net is too wide.
You've misunderstood. I do *not* want to catch the exception from sum(x, y, z).
I know you don't. My point with that example was to show how unlikely it is that someone would write that in the first place (since the code would always fail rather than in specific cases).
Sometimes a situation arises that there is a problem involving an exception being raised that is best fixed by catching the exception. Python does not provide much of a programmatic API for inspecting exceptions beyond simply choosing which class of exceptions to catch. That makes it important to limit the class of exceptions caught as carefully as possible.
I find it unlikely that TypeError (in particular) is of much use for repairing a situation, precisely because it is raised for situations where a value has an incorrect type. That sounds to me like either a bug in the code (and you don't fix bugs by catching exceptions, you fix them by changing the source code), or something that should be checked explicitly before making the call (e.g. if you can only sum ints and floats, and your data is from an unknown source, you should check the data before calling sum).
If the exception that needs to be caught is literally TypeError then it is not possible to be more precise than simply "except TypeError". I have seen code that parses the error messages but that seems flakey to me. The problem with "except TypeError" is that it also catches exceptions from situations where the exception should very rarely be caught e.g. sum(1, 2, 3).
This argument would be more convincing if you could quote real code where this has been a problem. In the case of sum(), it's no hardship to ensure that you pass a list of values, avoiding the sum(x, y, z) mistake, so if you wish to catch the TypeError from sum(a), that should not need this language change.
If the different cases that currently result in TypeError were broken down into more fine-grained exception classes then I think that would be good. A similar thing happened for OSError - in that case it was previously possible to distinguish cases using the errno attribute but it was awkward. In the case of TypeError there is nothing akin to the errno attribute so you either catch all TypeError or none.
And that's exactly the difference. For OSError it is *obviously* useful to catch the exception and take different actions based on the errno value, and using separate subclasses makes such code more robust. I have seen many such examples in real code (my own, and others'). But where are the examples showing that TypeError needs to be more granular? I find Serhiy's examples insufficiently convincing. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On Fri, Sep 03, 2021 at 05:31:33PM -0700, Guido van Rossum wrote:
I know you don't. My point with that example was to show how unlikely it is that someone would write that in the first place (since the code would always fail rather than in specific cases).
I have code that does something similar, as feature-detection. I want to be able to call gcd with any number of items, but older versions don't support that. from math import gcd try: gcd() except TypeError: # support arbitrary arguments def gcd(*args): # implementation goes here In this specific case, I can safely catch TypeError, because with no arguments at all, what else could it be? But a ParameterError exception would express my intent better. And other function calls may not be so easily distinguished. Here's another example: try: it = zip(a, b, strict=True) except TypeError: ... I can get away with catching TypeError because zip doesn't immediately iterate over the arguments. But that may not always be the case: from some_library import interleave # interleave([1,2,3], [4,5,6]) --> [1, 4, 2, 5, 3, 6] try: list_of_pairs = interleave(a, b, strict=True) except TypeError: # meaning what? In this hypothetical example, it would be good to distinguish between *wrong type* TypeErrors, and *wrong parameter* TypeErrors.
I find it unlikely that TypeError (in particular) is of much use for repairing a situation, precisely because it is raised for situations where a value has an incorrect type.
But not *only* for those situations. It is also used for situations where the number of arguments, or the keyword names, are wrong. And that can be fixed by retrying the call, possibly by calling a slower alternative. This may not seem appealing to you if you mostly or exclusively write code targetting a single version of Python, but if your code has to work with multiple versions, or if you are using third-party libraries where the API of functions may change, then I think it is useful to be able to distinguish parameter errors (wrong number of arguments, or wrong keywords) from the case where the arguments have the wrong type. I've often done this, and *mostly* I've been lucky enough that I could come up with a call where the TypeError could only mean something like "invalid keyword argument". But it would be useful to be able to express that more directly. -- Steve
On Fri, Sep 03, 2021 at 09:32:26AM -0700, Guido van Rossum wrote:
The question is, would anyone ever want to make a distinction between the two in *real* code? I find it unlikely that someone would write
try: sum(x, y, z) except TypeError: ...
Not for sum specifically, but yes, there are similar cases where I would. This is especially useful when using feature-detection rather than version-checking. E.g. `min` and `max` now take a key parameter, but old versions didn't: # This is in 2.4 >>> min(['a'], key=len) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: min() takes no keyword arguments A more recent example is math.gcd() which used to only take exactly two arguments but now takes an arbitrary number of arguments. We can use feature-detection to distinguish the two cases: gcd() # in Python 3.5 --> TypeError: gcd() takes exactly 2 arguments (0 given) gcd() # in Python 3.9 --> returns 0 Looking into the future, it would be useful to be able to distinguish between: - passing the correct number of arguments but wrong values (ValueError or similar) or wrong types (TypeError or AttributeError); - and passing the wrong number of arguments, or invalid keywords. That second case is currently a TypeError. I proposed a new subclass of TypeError for that purpose, ParameterError: https://mail.python.org/archives/list/python-ideas@python.org/message/MXPCNE... -- Steve
I guess having subclass for implementation errors to distinguish will be very helpful, Typeerror has become very generic and finding solution is like searching a needle in haystack for the new developers. Eg- TypeError: ‘int’ object is not iterable students=int(input('Please enter the number of students in the class: ')) for number in students: math_grade=(input("Enter student's Maths grade: ")) science_grade=(input("Enter student's Science grade: ")) social_grade=(input("Enter student's Scoial grade: ")) Common homeworks/tutorial for beginners who find difficult to understand why this error occurred. So a fine grained exception would be lot easier to understand and resolve quickly. *List of TypeErrors* - https://itsmycode.com/tag/typeerror/
On Sun, Sep 12, 2021 at 10:49 PM Ram Krishna <srinivasr2007@gmail.com> wrote:
I guess having subclass for implementation errors to distinguish will be very helpful, Typeerror has become very generic and finding solution is like searching a needle in haystack for the new developers.
Eg- TypeError: ‘int’ object is not iterable
students=int(input('Please enter the number of students in the class: '))
for number in students: math_grade=(input("Enter student's Maths grade: ")) science_grade=(input("Enter student's Science grade: ")) social_grade=(input("Enter student's Scoial grade: "))
Common homeworks/tutorial for beginners who find difficult to understand why this error occurred. So a fine grained exception would be lot easier to understand and resolve quickly.
Learning how to debug is part of learning to write software. (Maybe the biggest part.) Changing the type of that TypeError won't help; the key is figuring out why you're trying to iterate over an integer. The exception text is, to new developers, far more important than the actual type; I'd say that the type only really becomes significant when you're trying to catch the exception - that is to say, when exceptions DON'T mean errors. Also, novice programmers often forget (or fail to notice) that Python exceptions point you to the exact place where the error happened (especially in 3.10+); IME pointing someone to the right line of code is far more valuable than identifying the cause of the error, unless all of your students are creating the exact same bugs. (And sometimes even then. Maybe you have an exercise that is specifically designed to guide someone towards a wrong piece of code, experience a particular bug, and learn from it.) Most novices that I've taught have gone straight for the exception message, ignored the type name at the start, and ignored the line of code. And if I'm completely honest, I've made that same mistake myself, too - ended up looking in completely the wrong place... (The one thing that often trips people up is that, if an exception points to line X, the bug might be on line X-1, especially if it's a missed close parenthesis or something. I don't think there's an easy technical solution to that, but it's something I do have to point out to people fairly often.) ChrisA
12.09.21 07:48, Ram Krishna пише:
I guess having subclass for implementation errors to distinguish will be very helpful, Typeerror has become very generic and finding solution is like searching a needle in haystack for the new developers.
Eg- TypeError: ‘int’ object is not iterable
students=int(input('Please enter the number of students in the class: '))
for number in students: math_grade=(input("Enter student's Maths grade: ")) science_grade=(input("Enter student's Science grade: ")) social_grade=(input("Enter student's Scoial grade: "))
Common homeworks/tutorial for beginners who find difficult to understand why this error occurred. So a fine grained exception would be lot easier to understand and resolve quickly.
My proposition does not change the type of exception here. It is a vanilla TypeError: you use a value of improper type in operation. A new implementation error would be raised if you implement your own iterable class and return int in __iter__(). Most beginners will never see such errors because it is an advanced topic.
participants (9)
-
Chris Angelico
-
Christopher Barker
-
Greg Ewing
-
Guido van Rossum
-
Oscar Benjamin
-
Ram Krishna
-
Serhiy Storchaka
-
Steven D'Aprano
-
Thomas Grainger