In the improved error message [0] how are they able to tell nested attributes without having a big impact in performance? Or maybe this has a big impact on performance, then using exceptions for control flow is deprecated?
...
print(container.area)
> AttributeError: 'Container' object has no attribute 'area'. Did you mean: 'inner.area'?[0] -- https://docs.python.org/3.15/whatsnew/3.15.html#improved-err...
Here's the relevant diff: https://github.com/python/cpython/pull/137968/files#diff-966...
Search is limited to 20 attributes and non-descriptors only to avoid arbitrary code execution.
I assume constructing AttributeErrors isn't highly performance sensitive.
In Python, an iterator raises a StopIteration exception to indicate to the for loop that the iterator is done iterating.
In Python, the VM raises a KeyboardInterrupt exception when the user hits ctrl+c in order to unwind the stack, run cleanup code and eventually exit the program.
Python is a quite heavy user of exceptions for control flow.
Typically yes, but not in Python. In Python it is quite common and accepted, and sometimes even recommended as Pythonic to use exceptions for control flow. See iterators, for example.
I really dislike this too, but that’s how it is.
Using exceptions for flow control has always been a bad idea, despite what they might have said. Perhaps they are generating that message lazily though?
On the other hand it's not like Python really cares about performance....
All iterators in Python use exceptions for flow control, as do all context managers for the abort/rollback case, and it is generally considered Pythonic to use single-indexing (EAFP) instead of check-then-get (LBYL) - generally with indexing and KeyError though and less commonly with attribute access and AttributeError.
[heavy green check mark]
[red x] The latter form also has the genuine disadvantage that nothing ensures the two keys are the same. I've seen typos there somewhat often in code reviews.Last time I measured it, handling KeyError was also significantly faster than checking with “key in collection.” Also, as I was surprised to discover, Python threads are preemptively scheduled, GIL notwithstanding, so it’s possible for the key to be gone from the dictionary by the time you use it, even if it was there when you checked it. Although if you’re creating a situation where this is a problem, you probably have bigger issues.
I thought I knew enough about python culture but TIL
https://realpython.com/python-lbyl-vs-eafp/#errors-and-excep...
to me something like
is fine and isn’t subject to your disadvantage.You should do normally do
Wouldn't this be a little cleaner?
If valid `data` can be zero, an empty string, or anything else “falsy”, then your version won’t handle those values correctly. It treats them the same as `None`, i.e. not found.
:facepalm:
No, this would crash with numpy arrays, pandas series and such, with a ValueError: The truth value of an array with more than one element is ambiguous.
That behaves differently (eg if collection["key"] = 0)
No, truthiness (implicit bool coercion) is another thing you should avoid. This will do weird things if data is a string or a list or whatever.
it depends on what's in the if blocks
The value in the collection could be the actual value None, that’s different from the collection not having the key.
That's why I said "normally".
I would like to introduce you to StopIteration.