On Nov 29, 2016 9:43 AM, "Brett Cannon" <brett@python.org> wrote:
>
>
>
> 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.
It seems like this might need some care, though, to make sure that these extra attributes don't end up pinning objects in memory that shouldn't be? Actually I always assumed that was why AttributeError's message was constructed eagerly...
-n