Explain Codes LogoExplain Codes Logo

Does Python have a string 'contains' substring method?

python
functions
performance
best-practices
Nikita BarsukovbyNikita Barsukov·Sep 13, 2024
TLDR

Python does not have a built-in contains method for strings, but you can utilise the in operator to check if a string contains a substring:

if 'sub' in 'string with sub': print('Found!') # prints "Found!" because 'sub' is in 'string with sub'

This is the most common way to perform substring checking in Python.

It's Case-sensitive, Darling!

The in operator is case-sensitive, meaning 'Python' and 'python' are considered distinct:

# This will return False as 'Python' != 'python' print('Python' in 'I ♥ python')

However, you can achieve case-insensitive checks by converting both the string and substring to the same case using the .lower() method:

print('python'.lower() in 'I ♥ Python'.lower()) # ssssssmokin'!

Skipping Iterations: "I Don't Care About That!"

Sometimes, there are lines or elements you're not interested in. That's where not in comes to the rescue by excluding the unwanted ones:

ingredients = ["flour", "sugar", "eggs", "spam"] for ingredient in ingredients: if "spam" not in ingredient: # if you're not a Monty Python fan print(f"{ingredient} is approved!")

Where Is It? Getting the Index

The in operator only checks existence, but what if you need the location of a substring? str.find('substring') is perfect for the task:

# Fetch the index! index = "Whereabouts of 'ring'".find('ring') print(f"'ring' found at position {index}!")

If the substring is not found, it returns -1. If you'd rather raise an exception in such cases, str.index('substring') does exactly that:

try: pos = "Tinker Bell".index('Peter Pan') # uh-oh, he's not here! except ValueError: print("Substring not found. Fly again!")

Level Up: Advanced Substring Eyeballing

Literal checks are fine, but sometimes you need more firepower:

  • str.startswith('sub') or str.endswith('sub') for substring checks at specific positions
  • Using the fuzzy magic of Levenshtein package for approximate matches (looks like we're playing Quidditch!)
  • List comprehensions for substring hunting in a collection:
items = ["apple", "banana", "cherry", "date"] print([item for item in items if "a" in item]) # Let's 'a-pple'y the concept here

Internal Affair: The Intriguing __contains__

While technically there exists a str.__contains__('substring') method that implements the in operator action, it's considered Python-internal and should not be used directly. Stick with in as it's more pythonic:

# Naughty Naughty, you're caught-y! print("This is very naughty but totally works".__contains__('naughty'))

Also, when using in, ensure both objects are of the same type (str and str, or bytes and bytes). Type Safety first!

Inside Scoop: The in Operator's Speed

Why is the in operator so efficient? Python's bytecode gets translated into C code, which drives speedy performance. So, the speed of in is not just a magic trick, it's inside Python's heart (somewhere near its left ventricle).