Add safe `.get` method to List

Agreed. What you’re describing is just as much EAFP as exception handling is. It isn’t checking first and then attempting something; it’s simply attempting a thing that might fail, and coping with the failure.

At risk of being contrarian… I feel this thread has veered off topic.

The specific proposal was to add a get method to list (or Sequence) matching the semantics of that method on dict. Wouldn’t this be an alternative to either of the coding styles being discussed?

I guess I’m just confused about how resolving the coding style debate would help resolve the proposal.

5 Likes

Agreed, the EAFP/LBYL discussion is pretty much off topic.

To bring it back on-topic, I think the “safe get” requirement can easily be handled with a custom function if it’s that important. I don’t think “safe get” on lists is anywhere near as common in my experience as on dictionaries, so I don’t think the argument of “matching dict” holds much water.

I don’t like the “chained gets” style, nor do I think it’s particularly readable. For people who like it, there are libraries like glom (which I already mentioned) that do this.

There’s been a number of PEPs (exception handling expressions, non-aware operators) which would make this style possible without needing a list.get - but none of them have succeeded. Looking at why they failed might be instructive.

All of these are just my opinion - and while I’m not the final arbiter, you will need a core dev’s support to get anything implemented, so I’m explaining why I won’t be giving that support. Maybe another core dev thinks differently, but I haven’t seen any sign of that here.

3 Likes

I totally agree with this.

The reason I posted a suggestion (which was to use itertools.pairwise, which wasn’t in your linked threads afaict) was to suggest that the idea would be a lot more convincing with a motivating example that doesn’t have a nice solution already.

I understand, but it isn’t an applicable solution to the code example I wrote, where the final loop would have next_item be None (or default) when using a safe get. To get that, you’d have to check that the idx isn’t past the length of the lst, using whichever method has been described, which I think neatly demonstrates that this is tricky.

lst = list(range(10))
for idx, item in enumerate(lst):
    if idx + 1 >= len(lst):
        next_item = None # or "default"
    else:
        next_item = lst[idx + 1]
    print(item, next_item)

You could do:

from itertools import pairwise
lst = list(range(10))
for item, next_item in pairwise(lst + [None]):
    print(item, next_item)

or use itertools.chain if you only have an iterable instead of a list.

In general, my opinion is that indexing is less Pythonic than iteration. That’s why it seems that this get pattern rarely comes up. Indices are error-prone.

Indices are error-prone.

lol Indeed, thus this thread.

Given that multiple core devs have responded negatively to the idea, I don’t think there’s much to be gained from continuing to post. Thanks to everyone who’s contributed.

4 Likes