Python idiom to return first item or None?
The most Pythonic approach is what the most upvoted answer demonstrated, and it was the first thing to come to my mind when I read the question. Here's how to use it, first if the possibly empty list is passed into a function:
def get_first(l):
return l[0] if l else None
And if the list is returned from a get_list
function:
l = get_list()
return l[0] if l else None
New in Python 3.8, Assignment Expressions
Assignment expressions use the in-place assignment operator (informally called the walrus operator), :=
, new in Python 3.8, allows us to do the check and assignment in-place, allowing the one-liner:
return l[0] if (l := get_list()) else None
As a long-time Python user, this feels like we're trying to do too much on one line - I feel it would be better style to do the presumptively equally performant:
if l := get_list():
return l[0]
return None
In support of this formulation is Tim Peter's essay in the PEP proposing this change to the language. He didn't address the first formulation, but based on the other formulations he did like, I don't think he would mind.
Other ways demonstrated to do this here, with explanations
for
When I began trying to think of clever ways to do this, this is the second thing I thought of:
for item in get_list():
return item
This presumes the function ends here, implicitly returning None
if get_list
returns an empty list. The below explicit code is exactly equivalent:
for item in get_list():
return item
return None
if some_list
The following was also proposed (I corrected the incorrect variable name) which also uses the implicit None
. This would be preferable to the above, as it uses the logical check instead of an iteration that may not happen. This should be easier to understand immediately what is happening. But if we're writing for readability and maintainability, we should also add the explicit return None
at the end:
some_list = get_list()
if some_list:
return some_list[0]
slice or [None]
and select zeroth index
This one is also in the most up-voted answer:
return (get_list()[:1] or [None])[0]
The slice is unnecessary, and creates an extra one-item list in memory. The following should be more performant. To explain, or
returns the second element if the first is False
in a boolean context, so if get_list
returns an empty list, the expression contained in the parentheses will return a list with 'None', which will then be accessed by the 0
index:
return (get_list() or [None])[0]
The next one uses the fact that and returns the second item if the first is True
in a boolean context, and since it references my_list twice, it is no better than the ternary expression (and technically not a one-liner):
my_list = get_list()
return (my_list and my_list[0]) or None
next
Then we have the following clever use of the builtin next
and iter
return next(iter(get_list()), None)
To explain, iter
returns an iterator with a .next
method. (.__next__
in Python 3.) Then the builtin next
calls that .next
method, and if the iterator is exhausted, returns the default we give, None
.
redundant ternary expression (a if b else c
) and circling back
The below was proposed, but the inverse would be preferable, as logic is usually better understood in the positive instead of the negative. Since get_list
is called twice, unless the result is memoized in some way, this would perform poorly:
return None if not get_list() else get_list()[0]
The better inverse:
return get_list()[0] if get_list() else None
Even better, use a local variable so that get_list
is only called one time, and you have the recommended Pythonic solution first discussed:
l = get_list()
return l[0] if l else None