Python idiom to return first item or None

后端 未结 24 1940
清酒与你
清酒与你 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: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
    

提交回复
热议问题