On Tue, 29 Nov 2016 at 02:39 Nathaniel Smith <njs@pobox.com> wrote:
On Tue, Nov 29, 2016 at 1:05 AM, Victor Stinner
<victor.stinner@gmail.com> wrote:
> Hi,
>
> Python is optimized for performance. Formatting an error message has a
> cost on performances.

Sure, but we have to look at this on a case-by-case basis. Is there
really important code out there that's generating NameErrors or
SyntaxErrors in an inner loop? That seems unlikely to me.

Even IndexError I'm a bit skeptical about. I can believe that there's
code that intentionally generates and then catches IndexError, but
AttributeError in my experience is much more performance-sensitive
than IndexError, because every failed hasattr call allocates an
AttributeError and hasattr is commonly used for feature checks. Yet
AttributeError has a much more informative (= expensive) message than
IndexError:

In [1]: object().a
AttributeError: 'object' object has no attribute 'a'

In [2]: list()[0]
IndexError: list index out of range

One way to make this cheap is to have a reasonable default message and use attributes on the exceptions trigger the use of the default message. Nearly a year ago I filed a bunch of issues for ideas on providing attributes on exceptions where it made sense, e.g. an index attribute on IndexError (http://bugs.python.org/issue18162). If we did this then for classes like IndexError there constructor could be `IndexError(index=10, start=0, end=3)` and then __str__() can lazily construct the string representation using a default message, e.g. `"index {} is out of range of{} to {}".format(index, start, end)`. Make the arguments keyword-only and they become backwards-compatible and so the only overhead you pay for these richer messages are keyword-based construction if you simply never access the repr for the exception.