Explain Codes LogoExplain Codes Logo

Is there a short contains function for lists?

python
performance
collections
best-practices
Alex KataevbyAlex Kataev·Nov 19, 2024
TLDR

Use Python's membership operators, in and not in, to verify an item's existence in a list:

# Check for the hidden apple! print('apple' in ['apple', 'banana', 'cherry']) # returns True

This one-liner will return True if 'apple' is in the list, and False otherwise.

Performance breakdown

Although it's straightforward to use in or not in to search within list or tuple, be aware that this check has an average time complexity of O(n). However, using sets or dictionaries can offer faster membership checks (around O(1)) because of how they internally handle data.

If you're into custom classes, you can create your own containment logic by implementing a __contains__ method:

class CustomContainer: def __contains__(self, item): # Imagine this logic is as unique as a snowflake! return True if item == 'snowflake' else False

Remember, if you use list.index(item) it'll raise a ValueError, not return -1, when the item isn't found. The next function with a list comprehension can serve as a safe alternative:

# Finding a needle in a haystack, the Python way! is_present = next((True for item in my_list if item == 'needle'), False)

Performance considerations and alternatives

Lists are comfortable, but not always fast

With large lists, it may be beneficial to convert your list to a set for improving membership check performance:

# Unlike my old truck, this actually gets faster with more use! my_set = set(my_large_list) print('value' in my_set)

Let's play Collections

Even though sets and dictionaries provide faster lookups, they require more memory and they don't keep the order of elements.

Meet next()

You can use the next() function with a generator expression for complex checks within a list. This method terminates the iteration immediately on finding a match—like stopping a movie when it gets way too boring!

# It's like swiping on a dating app until you find a match! is_present = next((item for item in my_list if condition(item)), None) is not None

__contains__ to the rescue

Mastering the use of custom __contains__ methods can result in code that's as clean and shiny as a new metal band t-shirt.

Safely getting the index

To safely get an element's index with a default, use next with the enumerate function like a tag team of wrestlers:

# Not every item gets to be the hero, but they all deserve a place! index_or_default = next((index for index, value in enumerate(my_list) if value == 'value'), -1)