430

I'm calling a bunch of methods that return a list. The list may be empty. If the list is non-empty, I want to return the first item; otherwise, I want to return None. This code works:

def main():
    my_list = get_list()
    if len(my_list) > 0:
        return my_list[0]
    return None

but it seems to me that there should be a simple one-line idiom for doing this. Is there?

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
  • 32
    btw, on Python 2.6+ you could use `next(iter(your_list), None)` instead of `first_item(your_list)` assuming `your_list` is not `None` (`get_first_list()` and `get_second_list()` must always return an iterable). – jfs Dec 13 '11 at 15:57
  • 1
    I think you mean `next(iter(your_list))`, since if you supply a second argument to `iter`, you're telling it that the first argument is callable. – Robert Rossney Dec 17 '11 at 20:53
  • 8
    No, `None` here is the second parameter for [`next()`](http://docs.python.org/library/functions.html#next), not [`iter()`](http://docs.python.org/library/functions.html#iter). `next()` returns its second parameter if given instead of raising `StopIteration` if `your_list` is empty. – jfs Dec 17 '11 at 22:59
  • Solution suggested by @J.F.Sebastian exists with duplicate question: http://stackoverflow.com/a/18533669/144408 – shahjapan Jun 24 '16 at 09:35
  • You don't need to apologise for your question, it's a question a lot of people have. I do like terse code. We all do. Python is known for it. It's part of what makes it more readable and quicker to write. – NeilG Feb 22 '21 at 23:42

25 Answers25

361

Python 2.6+

next(iter(your_list), None)

If your_list can be None:

next(iter(your_list or []), None)

Python 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

Example:

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

Another option is to inline the above function:

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

To avoid break you could write:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

Where:

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 1
    That last option is almost exactly what I'm looking for: it's clear, it works, and it doesn't require me to define a new function. I'd say "exactly" if the break were somehow not needed, because the risk of omitting it is not insignificant. But this approach has the ring of truth. – Robert Rossney Dec 16 '08 at 00:56
  • Oh, I don't like this at all. If any item in the list evaluates False, that value is discarded and replaced. If you have an empty string `""` in the list, that is discarded and replaced by an empty list `[]`. If you have a 0, also replaced by `[]`. If you have `False` in there, also replaced. Etc. You might get away with this in a specific case, but this is a bad habit to develop. – steveha Nov 22 '09 at 04:10
  • 5
    @steveha: `bool(lst) `tells us whether `len(lst) > 0` it doesn't tell us anything about what items `lst` contains e.g., `bool([False]) == True;` therefore the expression `[False] or []` returns `[False]`, the same is for `[0] or [] ` it returns `[0]`. – jfs Nov 27 '09 at 23:43
  • @RobertRossney: I've added `yield_first()` to avoid `break` statement. – jfs May 26 '12 at 19:47
  • Perhaps you should prefer using a tuple instead of a list? – Christopher Smith Jan 19 '13 at 20:12
  • @ChristopherSmith: A list is semantically correct here. A `for`-loop implies homogeneous sequence. See [Tuples have structure, lists have order](http://stackoverflow.com/a/626871/4279). Don't microoptimize unless a profiler says so. – jfs Jan 19 '13 at 20:36
  • I think the Python 2.6+ version could be improved even more: `next(iter(your_list or [None]))` – Andrew Kravchuk Apr 24 '18 at 15:42
  • `next(iter(your_list), None)` should be sufficient. – Thomas Ahle May 22 '18 at 12:59
  • @ThomasAhle [it were true](https://stackoverflow.com/questions/363944/python-idiom-to-return-first-item-or-none#comment10507959_363944) if `your_list` couldn't be `None`. – jfs May 22 '18 at 13:06
  • @jfs Right, but the question doesn't state that the list may be `None`. – Thomas Ahle May 23 '18 at 10:57
  • @ThomasAhle what do you think `list_or_none` name means? – jfs May 23 '18 at 11:04
  • @jfs in the first "This code works" section it's just called `my_list`. The `list_to_none` part is labeled "can certainly be accomplished with". Just saying that for OP and most people finding this question, `iter(your_list)` will work fine. – Thomas Ahle May 23 '18 at 11:09
  • 1
    @ThomasAhle: both are true. I've updated the answer to provide the solution for non-None case. – jfs May 23 '18 at 11:45
  • `next(iter(your_list or []), None)` is incredibly unreadable and unexpressive. Please use `your_list[0] if your_list else None` instead. – Aykhan Hagverdili Aug 28 '23 at 08:43
  • @AykhanHagverdili notice that there is [`a[0] if a else None` answer](https://stackoverflow.com/a/363995/4279) posted in 2008 even before my answer (15 years ago). Both can be used e.g., "next(iter" may be preferable if the input is an arbitrary iterable (not just a sequence). Given the walrus operator the "if/else" variant can be used even with expressions now. – jfs Aug 28 '23 at 18:45
  • @jfs I wasn't asking you to use that, sorry for the misunderstanding. I was asking people reading this answer to prefer the other one. – Aykhan Hagverdili Aug 28 '23 at 21:14
280

The best way is this:

a = get_list()
return a[0] if a else None

You could also do it in one line, but it's much harder for the programmer to read:

return (get_list()[:1] or [None])[0]
efotinis
  • 14,565
  • 6
  • 31
  • 36
  • One word of caution, if you are writing code that needs to work for a list OR a NumPy array then this pattern will error for the numpy array. Prefer https://stackoverflow.com/a/365934/5167537 instead: `next(iter(your_list), None)` – Benjamin Brandt Mar 30 '22 at 22:19
100
(get_list() or [None])[0]

That should work.


BTW I didn't use the variable list, because that overwrites the builtin list() function.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
recursive
  • 83,943
  • 34
  • 151
  • 241
  • 5
    This is clever and works, but I think "return foo[0] if foo else None" as suggested by efotinis is a little easier to follow for maintenance. – Jay Dec 12 '08 at 20:21
  • 4
    The question was asking for a one line solution, so I ruled that out. – recursive Dec 12 '08 at 20:25
  • Neither of those expressions work if get_list() returns None; you get "TypeError: 'NoneType' object is unsubscriptable." or "TypeError: unsupported operand type(s) for +: 'NoneType' and 'list'." – Robert Rossney Dec 13 '08 at 19:46
  • 4
    In the question, it says that the methods return lists, of which None is not one. So given the requirements, I still believe they both work. – recursive Dec 13 '08 at 20:30
  • Should work now if get_list() returns None since it doesn't get subscripted or added anymore. – Robert Feb 01 '17 at 23:51
38

The most python idiomatic way is to use the next() on a iterator since list is iterable. just like what @J.F.Sebastian put in the comment on Dec 13, 2011.

next(iter(the_list), None) This returns None if the_list is empty. see next() Python 2.6+

or if you know for sure the_list is not empty:

iter(the_list).next() see iterator.next() Python 2.2+

Devy
  • 9,655
  • 8
  • 61
  • 59
  • 1
    This has the advantage that you don't have to assign your list to a variable like the `return l[0] if l else None` if the list was a libcomp. When the list is actually a genexpr this is even better since you don't have to construct the whole list like in `next(iter(x for x in range(10) if x % 2 == 0), None)` – RubenLaguna Feb 11 '16 at 09:25
  • 1
    If you know for sure `the_list` is not empty, you would write `the_list[0]`. – kaya3 Dec 23 '19 at 17:37
15

If you find yourself trying to pluck the first thing (or None) from a list comprehension you can switch to a generator to do it like:

next((x for x in blah if cond), None)

Pro: works if blah isn't indexable Con: it's unfamiliar syntax. It's useful while hacking around and filtering stuff in ipython though.

Aidan Kane
  • 3,856
  • 2
  • 25
  • 28
13

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
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
11

The OP's solution is nearly there, there are just a few things to make it more Pythonic.

For one, there's no need to get the length of the list. Empty lists in Python evaluate to False in an if check. Just simply say

if list:

Additionally, it's a very Bad Idea to assign to variables that overlap with reserved words. "list" is a reserved word in Python.

So let's change that to

some_list = get_list()
if some_list:

A really important point that a lot of solutions here miss is that all Python functions/methods return None by default. Try the following below.

def does_nothing():
    pass

foo = does_nothing()
print foo

Unless you need to return None to terminate a function early, it's unnecessary to explicitly return None. Quite succinctly, just return the first entry, should it exist.

some_list = get_list()
if some_list:
    return list[0]

And finally, perhaps this was implied, but just to be explicit (because explicit is better than implicit), you should not have your function get the list from another function; just pass it in as a parameter. So, the final result would be

def get_first_item(some_list): 
    if some_list:
        return list[0]

my_list = get_list()
first_item = get_first_item(my_list)

As I said, the OP was nearly there, and just a few touches give it the Python flavor you're looking for.

gotgenes
  • 38,661
  • 28
  • 100
  • 128
  • 1
    Why is 'list' a reserved word in python? Or, more to the point, where does it say that 'list' is a reserver word in python? Or, more to the point, how did you verify that 'list' is a reserved word in python? Considering that I can declare a variable named 'list', it is *clearly* not a reserved word. – Lasse V. Karlsen Dec 12 '08 at 22:48
  • 2
    Point taken. The truly reserved words in Python can be found here http://tinyurl.com/424663 However, it's a good idea to consider builtin functions and types as reserved. list() actually generates a list. Same goes for dict, range, etc. – gotgenes Dec 12 '08 at 23:01
  • I would combine the last two lines, eliminating the temporary variable (unless you need my_list further). That improves readability. – Svante Dec 13 '08 at 19:53
  • This is pretty much the answer I was gravitating towards. – Robert Rossney Dec 13 '08 at 20:09
  • 1
    `get_first_item` should accept a `default` parameter (like `dict.get`) which defaults itself to None. Thus the function interface communicates explicitly what happens if `my_list` is empty. – jfs Dec 13 '08 at 23:21
  • I've posted get_first() implementation as an answer http://stackoverflow.com/questions/363944/python-idiom-to-return-first-item-or-none#365934 – jfs Dec 13 '08 at 23:33
7

Regarding idioms, there is an itertools recipe called nth.

From itertools recipes:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

If you want one-liners, consider installing a library that implements this recipe for you, e.g. more_itertools:

import more_itertools as mit

mit.nth([3, 2, 1], 0)
# 3

mit.nth([], 0)                                             # default is `None`
# None

Another tool is available that only returns the first item, called more_itertools.first.

mit.first([3, 2, 1])
# 3

mit.first([], default=None)
# None

These itertools scale generically for any iterable, not only for lists.

pylang
  • 40,867
  • 14
  • 129
  • 121
3
for item in get_list():
    return item
A. Coady
  • 54,452
  • 8
  • 34
  • 40
3

Frankly speaking, I do not think there is a better idiom: your is clear and terse - no need for anything "better". Maybe, but this is really a matter of taste, you could change if len(list) > 0: with if list: - an empty list will always evaluate to False.

On a related note, Python is not Perl (no pun intended!), you do not have to get the coolest code possible.
Actually, the worst code I have seen in Python, was also very cool :-) and completely unmaintainable.

By the way, most of the solution I have seen here do not take into consideration when list[0] evaluates to False (e.g. empty string, or zero) - in this case, they all return None and not the correct element.

rob
  • 36,896
  • 2
  • 55
  • 65
  • In Python, it is considered good style to write `if lst:` rather than `if len(lst) > 0:`. Also, don't use Python keywords as variable names; it ends in tears. It's common to use `L` or `lst` as the variable name for some list. I'm sure in this case you didn't mean to suggest actually using `list` as a variable name, you just meant "some list". And, +1 for "when lst[0] evaluates to False". – steveha Nov 22 '09 at 04:15
  • Yes, I was just maintaining the same kind of name of OP, for better clarity. But you are definitely right: some care should be always be taken not to override Python keywords. – rob Nov 22 '09 at 22:33
  • "you do not have to get the coolest code possible." - bonus points now for pointing this out :) – jtlz2 Feb 07 '23 at 20:03
  • @steveha Good style maybe - but only if the reader already knows that an empty list will evaluate to False - which beginners often don't and may therefore waste time staring at this.... Bring on the Walrus operator.... :) – jtlz2 Feb 07 '23 at 20:04
  • 1
    @jtlz2 When I said "it is considered good style" I was not just making stuff up. The essential style guide every Python developer should read is PEP 8, and in PEP 8 there is a section you can search for that says: "For sequences, (strings, lists, tuples), use the fact that empty sequences are false" This specifically recommends `if lst:` Of course you can choose to follow or not follow the PEP 8 recommendations. – steveha Mar 07 '23 at 04:44
3

my_list[0] if len(my_list) else None

Nicholas Hamilton
  • 10,044
  • 6
  • 57
  • 88
2

Not sure how pythonic this is but until there is a first function in the library I include this in the source:

first = lambda l, default=None: next(iter(l or []), default)

It's just one line (conforms to black) and avoids dependencies.

laktak
  • 57,064
  • 17
  • 134
  • 164
1

Out of curiosity, I ran timings on two of the solutions. The solution which uses a return statement to prematurely end a for loop is slightly more costly on my machine with Python 2.5.1, I suspect this has to do with setting up the iterable.

import random
import timeit

def index_first_item(some_list):
    if some_list:
        return some_list[0]


def return_first_item(some_list):
    for item in some_list:
        return item


empty_lists = []
for i in range(10000):
    empty_lists.append([])

assert empty_lists[0] is not empty_lists[1]

full_lists = []
for i in range(10000):
    full_lists.append(list([random.random() for i in range(10)]))

mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)

if __name__ == '__main__':
    ENV = 'import firstitem'
    test_data = ('empty_lists', 'full_lists', 'mixed_lists')
    funcs = ('index_first_item', 'return_first_item')
    for data in test_data:
        print "%s:" % data
        for func in funcs:
            t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
                func, data), ENV)
            times = t.repeat()
            avg_time = sum(times) / len(times)
            print "  %s:" % func
            for time in times:
                print "    %f seconds" % time
            print "    %f seconds avg." % avg_time

These are the timings I got:

empty_lists:
  index_first_item:
    0.748353 seconds
    0.741086 seconds
    0.741191 seconds
    0.743543 seconds avg.
  return_first_item:
    0.785511 seconds
    0.822178 seconds
    0.782846 seconds
    0.796845 seconds avg.
full_lists:
  index_first_item:
    0.762618 seconds
    0.788040 seconds
    0.786849 seconds
    0.779169 seconds avg.
  return_first_item:
    0.802735 seconds
    0.878706 seconds
    0.808781 seconds
    0.830074 seconds avg.
mixed_lists:
  index_first_item:
    0.791129 seconds
    0.743526 seconds
    0.744441 seconds
    0.759699 seconds avg.
  return_first_item:
    0.784801 seconds
    0.785146 seconds
    0.840193 seconds
    0.803380 seconds avg.
gotgenes
  • 38,661
  • 28
  • 100
  • 128
0
try:
    return a[0]
except IndexError:
    return None
limscoder
  • 3,037
  • 2
  • 23
  • 37
  • 1
    Exceptions generally aren't used for flow control. – Matt Green Dec 12 '08 at 20:33
  • I don't think making this code longer and adding exception-handling to it is exactly the idiom I was looking for. – Robert Rossney Dec 12 '08 at 21:26
  • 6
    But this is a common Python idiom! For performance reasons, you might not use it; you will get better performance out of `if len(a) > 0:` but this is considered good style. Note how well this expresses the problem: "try to extract the head of a list, and if that doesn't work out, return `None`". Google search for "EAFP" or look here: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#eafp-try-except-example – steveha Nov 22 '09 at 04:23
  • 1
    @steveha It depends on your data. If len(a) is usually > 0 and len(a) < 1 is a rare state, catching the exception will actually be more performant. – limscoder Jun 10 '12 at 21:49
  • @limscoder, I agree with you. I just didn't get into the details of *when* you might not use it for performance reasons; I didn't say you would never use this. – steveha Jun 11 '12 at 01:34
0
def head(iterable):
    try:
        return iter(iterable).next()
    except StopIteration:
        return None

print head(xrange(42, 1000)  # 42
print head([])               # None

BTW: I'd rework your general program flow into something like this:

lists = [
    ["first", "list"],
    ["second", "list"],
    ["third", "list"]
]

def do_something(element):
    if not element:
        return
    else:
        # do something
        pass

for li in lists:
    do_something(head(li))

(Avoiding repetition whenever possible)

ttepasse
  • 746
  • 4
  • 9
0

Borrowing more_itertools.first_true code yields something decently readable:

def first_true(iterable, default=None, pred=None):
    return next(filter(pred, iterable), default)

def get_first_non_default(items_list, default=None):
    return first_true(items_list, default, pred=lambda x: x!=default)
mirekphd
  • 4,799
  • 3
  • 38
  • 59
0

Following code covers several scenarios by using lambda:

l1 = [1,2,3]
l2 = []
l3 = None
first_elem = lambda x: x[0] if x else None
print(first_elem(l1))
print(first_elem(l2))
print(first_elem(l3))
rkachach
  • 16,517
  • 6
  • 42
  • 66
-1

Probably not the fastest solution, but nobody mentioned this option:

dict(enumerate(get_list())).get(0)

if get_list() can return None you can use:

dict(enumerate(get_list() or [])).get(0)

Advantages:

-one line

-you just call get_list() once

-easy to understand

Eric Marcos
  • 2,637
  • 2
  • 14
  • 12
-1

How about this:

(my_list and my_list[0]) or None

Note: This should work fine for lists of objects but it might return incorrect answer in case of number or string list per the comments below.

VitalyB
  • 12,397
  • 9
  • 72
  • 94
-1

My use case was only to set the value of a local variable.

Personally I found the try and except style cleaner to read

items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item

than slicing a list.

items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item
bkowshik
  • 581
  • 4
  • 6
-1

Using the and-or trick:

a = get_list()
return a and a[0] or None
titaniumdecoy
  • 18,900
  • 17
  • 96
  • 133
-2

You could use Extract Method. In other words extract that code into a method which you'd then call.

I wouldn't try to compress it much more, the one liners seem harder to read than the verbose version. And if you use Extract Method, it's a one liner ;)

Stephane Grenier
  • 15,527
  • 38
  • 117
  • 192
-2

Several people have suggested doing something like this:

list = get_list()
return list and list[0] or None

That works in many cases, but it will only work if list[0] is not equal to 0, False, or an empty string. If list[0] is 0, False, or an empty string, the method will incorrectly return None.

I've created this bug in my own code one too many times !

Kenly
  • 24,317
  • 7
  • 44
  • 60
Clint Miller
  • 15,173
  • 4
  • 37
  • 39
-3

isn't the idiomatic python equivalent to C-style ternary operators

cond and true_expr or false_expr

ie.

list = get_list()
return list and list[0] or None
Jimmy
  • 89,068
  • 17
  • 119
  • 137
  • If a[0] is the number 0 or the empty string (or anything else that evaluates to false), this will return None instead of what a[0] actually is. – Adam Rosenfield Dec 12 '08 at 22:00
-3
if mylist != []:

       print(mylist[0])

   else:

       print(None)
the_unknown_spirit
  • 2,518
  • 7
  • 34
  • 56
PrabhuPrakash
  • 261
  • 2
  • 7