The in operator. It reads like English and it's the fastest way.
line = "2026-10-07 09:02 ERROR disk full on /var" print("ERROR" in line) print("WARNING" in line)
True False
Ignoring upper and lower case
in is case-sensitive. Lower both sides first; casefold() is the stricter version of lower() for text in other languages, such as German ß:
subject = "URGENT: Invoice overdue" print("urgent" in subject) print("urgent" in subject.casefold())
False True
Where is it?
find() returns the position, or -1 if it isn't there. (index() does the same but raises ValueError instead of returning -1.)
path = "/home/ada/projects/site/app.py" print(path.find("projects")) print(path.find("downloads")) print(path.count("/"))
10 -1 5
Don't write if path.find("x"): as a yes/no check. A match at the very start returns 0, which is false, and a miss returns -1, which is true: exactly backwards. Use in for yes or no.
Any of several words
message = "Your parcel is out for delivery today" keywords = ["refund", "delivery", "cancel"] print(any(word in message for word in keywords)) print([word for word in keywords if word in message])
True ['delivery']
Whole words only
in matches inside words too: "cat" in "concatenate" is True. When that's wrong, use a regular expression with \b, which means "word boundary":
import re for text in ["the cat sat", "concatenate", "Cat!"]: print(text, "->", bool(re.search(r"\bcat\b", text, re.IGNORECASE)))
the cat sat -> True concatenate -> False Cat! -> True
Starting or ending with something has its own methods, clearer than slicing: filename.endswith((".jpg", ".png")) and url.startswith("https://"). Both accept a tuple of options.