Indexable get method. [1,2,3].get(4) # None

After a bit of research, I found that this idea was suggested back in 2018, but the conversation stopped, and the topic was automatically closed.

Links to the original discussion:

I think it would be great to add a few more spoons of syntactic sugar for working with lists and other indexable objects. The idea is pretty simple to implement and doesn’t require major changes.

Currently, you might write:

myval = mylist[1] if len(mylist) > 1 else None
# or
try:
    myval = mylist[1]
except IndexError:
    myval = None

But wouldn’t it be cleaner and simpler to have:

myval = mylist.get(1)

A lot of people on Stack Overflow are asking about this functionality, and I agree it’s not an uncommon case. Maybe it’s time to take a second look at this idea? What do you think?

9 Likes

I like that this proposal follows the pattern established by dict.get(...). I could see myself using it.

4 Likes

It seems nice and clean and consistent with dict.

Are there many use cases after a list.get call that don’t require a subsequent test such as: if myval is None (or if myval =='Sentinel' if None is in the list)?

PEP 463 would like to say hi, too. Its rejection may provide some insights.

3 Likes

I like to do [myval] = mylist[1:2] or [None]

Nice hack, but may be confusing for those not deeply familiar with Python

1 Like

Can you show the motivating code where you want to do this?

Do you have examples? I don’t remember ever seeing that.

Case when some APIs return an empty list or a list with exactly one element, or if you need only the first element because the target structure doesn’t have a field for more than one:

response = requests.get("https://example.com")
phone_list = response.json()['phone']
phone_number = phone_list[0] if phone_list else None

A case with some libraries that return only batches when you need only the first element: For example, face detection algorithms might return a list of detected rectangles, but you might only care about the first one. (This is not the best example because, in the case of face detection, you might want to process 2+ detections separately; however, I can’t think of a better one at the moment.)

detected_faces = some_cv_lib.detect_faces('foo.jpg')
first_face = detected_faces[0] if detected_faces else None

Can’t provide enough examples because of 2 links limitation. There’s 5 links in the original discussion. And I can find few dozens more with google queries like ‘safe get method for list python’.

Also I found that this idea was already posted here in 2023 Add safe `.get` method to List - #3 by NoahTheDuke And even discussion with answer from Guido van Rossum Mailman 3 What about having a .get(index, default) method for arrays like we have for dicts? - Python-ideas - python.org

So maybe it’s time to close this topic

Like this:

phone_number = phone_list[0] if phone_list else None

I fully support this, for tuples as well.

I’m a big fan of duck typing. I don’t use any type-checking tools and would never want to get into the kinds of messes that I see others create with them; but I sometimes annotate my interfaces as documentation, and use collections.abc typenames to do so. If I write something that conceptually expects an immutable mapping of integers to whatever, I’d like to be able to accept a list - or a tuple - transparently. That kind of thing is a big part of why I use Python. Having a .get method would help support my style of programming.

1 Like

This seems like much more of a “mess” than using type checking and having guarantees about what you can and can’t pass, and what a function accepting something can and can’t do.

That said, you can just pass dict(enumerate(x)) to convert a list[T] to a Mapping[int, T].