Python idiom to return first item or None

后端 未结 24 1718
清酒与你
清酒与你 2020-12-07 07:46

I\'m sure there\'s a simpler way of doing this that\'s just not occurring to me.

I\'m calling a bunch of methods that return a list. The list may be empty. If the

相关标签:
24条回答
  • 2020-12-07 08:18

    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

    0 讨论(0)
  • 2020-12-07 08:19

    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+

    0 讨论(0)
  • 2020-12-07 08:20
    (get_list() or [None])[0]
    

    That should work.

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

    Edit: I had a slightly simpler, but wrong version here earlier.

    0 讨论(0)
  • 2020-12-07 08:22

    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
    

    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
    
    0 讨论(0)
  • 2020-12-07 08:24
    try:
        return a[0]
    except IndexError:
        return None
    
    0 讨论(0)
  • 2020-12-07 08:29

    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 !

    0 讨论(0)
提交回复
热议问题