← Python lessons

Python Find an Item in a List: Return the Match or None

Part of a free Python course — sign up to save your progress and get AI hints.Sign up free

A search function can return the value it found, not just True or False. When nothing matches, it returns None so the caller can tell "found" from "not found".

Read Stopping a Search with return first. The examples also use range() and unpacking.

None is Python's value for "nothing here". A function that ends without a return also gives back None.

Return the matching item

Return the item itself inside the loop. After the loop, return None.

def find_long_word(words, length):
    for word in words:
        if len(word) >= length:
            return word
    return None

print(find_long_word(["cat", "zebra", "otter"], 5))
print(find_long_word(["cat", "dog"], 5))

The first call prints zebra, the first long enough word. otter is never checked. The second call finds nothing and prints None.

Check for None before using the result

The caller must handle the "not found" case. is None asks "is this the None value?". Use it rather than == None.

def find_long_word(words, length):
    for word in words:
        if len(word) >= length:
            return word
    return None

word = find_long_word(["cat", "dog"], 5)
if word is None:
    print("No long word")
else:
    print(word.upper())

Without the check, word.upper() would crash with AttributeError, because None has no upper() method.

Return a position instead of the item

Sometimes you need where the match is. Loop over range(len(...)) and return the index.

def first_index_over(scores, limit):
    for index in range(len(scores)):
        if scores[index] > limit:
            return index
    return None

print(first_index_over([40, 75, 90], 70))
print(first_index_over([40, 55], 70))

The first call prints 1: scores[1] is 75. The second prints None.

Watch out: a found value can look false

Index 0 and empty text "" are real answers, but they are falsy. if result: treats them like "not found".

def first_index_over(scores, limit):
    for index in range(len(scores)):
        if scores[index] > limit:
            return index
    return None

result = first_index_over([90, 40], 70)
if result:
    print("found at", result)
else:
    print("not found")  # wrong: the match is at index 0
if result is not None:
    print("found at", result)

The first if prints not found, which is wrong. is not None gets it right and prints found at 0.

Note: Returning None is the simplest "not found" signal. Real code sometimes raises an exception instead, or uses a built-in such as list.index() or str.find(). These examples leave out type hints such as str | None.

See also: Truthy and falsy values, Optional and Union types.

Your turn

Finish find_price(items, name). Each item is a [name, price] pair. Loop with for item_name, price in items:. Return the price of the first item called name, or None if there is none. Then print the result for "pear", and "Not sold" for "kiwi".

def find_price(items, name):
    # loop over the pairs, return the matching price,
    # and return None after the loop
    pass

stock = [["apple", 3], ["pear", 0], ["plum", 5]]
# print find_price(stock, "pear"),
# then print "Not sold" if find_price(stock, "kiwi") is None

Expected output

0
Not sold