How to use the 'in' operator in Python

Learn to use Python's 'in' operator. Explore different methods, tips, real-world applications, and how to debug common errors.

How to use the 'in' operator in Python
Published on: 
Tue
Mar 10, 2026
Updated on: 
Fri
Mar 13, 2026
The Replit Team

Python's in operator is a powerful tool. You use it to check for membership within strings, lists, and other iterable types. Its simple syntax makes your code clean and readable.

Here, you'll learn essential techniques and tips for the in operator. You will see real-world applications and get advice to debug common issues, so you can master its use in your projects.

Basic usage of in operator

fruits = ["apple", "banana", "cherry"]
if "banana" in fruits:
   print("Yes, banana is in the fruits list")--OUTPUT--Yes, banana is in the fruits list

The code demonstrates a simple membership test. The in operator checks if the string "banana" exists as an element within the fruits list. This operation returns a boolean value—True if the item is found, and False otherwise.

Because "banana" is in the list, the expression "banana" in fruits evaluates to True. The if statement then executes its code block, printing the confirmation message. This simple boolean check is the core of how the in operator drives conditional logic in Python.

Common uses of in operator

While the list example shows its basic function, the in operator's real power shines when you use it with other data types like strings and dictionaries.

Using in with different collection types

my_list = [1, 2, 3, 4, 5]
my_tuple = (1, 2, 3, 4, 5)
my_set = {1, 2, 3, 4, 5}

print(3 in my_list)
print(6 in my_tuple)
print(4 in my_set)--OUTPUT--True
False
True

The in operator works consistently across different collection types, including lists, tuples, and sets. It always returns a boolean value based on whether an element is present.

  • The expression 3 in my_list evaluates to True because 3 is an element.
  • 6 in my_tuple is False since 6 is missing from the tuple.
  • 4 in my_set returns True as 4 is found within the set.

Though the syntax is identical, checking for membership in a set is much faster than in a list or tuple. This makes sets the preferred choice when you need to perform many membership checks.

Using in with strings

text = "Python is powerful"
print("Python" in text)
print("python" in text)
print("power" in text)--OUTPUT--True
False
True

When you use the in operator with strings, it checks for the presence of a substring. This is a straightforward way to find a sequence of characters within a larger text.

  • The search is case-sensitive. This is why "Python" in text is True, while "python" in text evaluates to False.
  • It also finds partial matches, not just whole words. The expression "power" in text returns True because the substring "power" exists within the word "powerful".

Using in with dictionaries

person = {"name": "John", "age": 30, "city": "New York"}
print("name" in person)
print("John" in person)
print("age" in person.keys())
print(30 in person.values())--OUTPUT--True
False
True
True

With dictionaries, the in operator checks for keys by default—not values. This is why "name" in person evaluates to True, while checking for a value like "John" in person returns False.

  • To be explicit, you can check for keys using person.keys(), but it’s redundant since it's the default behavior.
  • To check if a value exists, you must use the .values() method. This is why 30 in person.values() correctly returns True.

Advanced techniques with in

With the fundamentals covered, you can now use the in operator for more advanced tasks, like creating powerful list comprehensions and defining custom membership logic.

Using in with list comprehensions

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
allowed = [2, 4, 6, 8]
filtered = [num for num in numbers if num in allowed]
print(filtered)--OUTPUT--[2, 4, 6, 8]

List comprehensions offer a compact way to build new lists, and using the in operator inside them creates a powerful filter. This one-liner builds the filtered list by iterating through numbers and keeping only the elements that are also present in the allowed list.

  • The expression loops through each num in the numbers list.
  • The condition if num in allowed checks for membership in the second list.
  • Only when the condition is True is the number added to the new list.

Implementing __contains__ for custom objects

class Temperature:
   def __init__(self, min_temp, max_temp):
       self.min_temp = min_temp
       self.max_temp = max_temp
   
   def __contains__(self, temp):
       return self.min_temp <= temp <= self.max_temp

normal_range = Temperature(36.5, 37.5)
print(36.8 in normal_range)
print(38.0 in normal_range)--OUTPUT--True
False

You can control how the in operator behaves with your own custom objects. To do this, you implement a special method called __contains__, which lets you define custom membership logic for your class.

In the Temperature example, the __contains__ method defines membership as a temperature falling within a specific range.

  • The check 36.8 in normal_range returns True because the value is within the object's range.
  • Similarly, 38.0 in normal_range is False because it's outside the defined limits.

Performance considerations with in

import timeit

list_time = timeit.timeit(stmt="42 in data", setup="data = list(range(1000))", number=10000)
set_time = timeit.timeit(stmt="42 in data", setup="data = set(range(1000))", number=10000)

print(f"List lookup time: {list_time:.6f} seconds")
print(f"Set lookup time: {set_time:.6f} seconds")--OUTPUT--List lookup time: 0.040781 seconds
Set lookup time: 0.001912 seconds

The performance of the in operator depends heavily on the data type you're using. This code measures the time it takes to find an element in a list versus a set. As the output shows, checking for membership in a set is dramatically faster.

  • With lists, Python performs a linear search. It checks each item one by one until it finds a match, which can be slow for large lists.
  • Sets use a hash table, which allows for direct lookups. This lets Python find an item almost instantly, regardless of the set's size.

Because of this efficiency, you should use sets instead of lists when your code needs to perform many membership checks.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. You can describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

The techniques you've learned with the in operator can be turned into production-ready tools. For example, Replit Agent can help you:

  • Build a content filter that checks user input against a blocklist of forbidden words.
  • Create a configuration validator that ensures a settings file contains all required keys before launch.
  • Deploy a log scanner that flags lines containing specific error codes or keywords for quick debugging.

Turn your idea into a functional application. Describe what you want to build, and Replit Agent will write, test, and deploy the code for you.

Common errors and challenges

Even with its simple syntax, the in operator has a few common pitfalls that can trip you up if you're not careful.

Forgetting case sensitivity when using in with strings

A frequent mistake is forgetting that string comparisons are case-sensitive. If you check for a lowercase substring in an uppercase string, the in operator will return False, even if the word is present.

  • For example, 'error' in 'ERROR: System Failure' evaluates to False.
  • To avoid this, you can convert both the string and the substring to the same case—typically lowercase—using the .lower() method before performing the check.

Incorrect value checking with in and dictionaries

It's easy to forget that the in operator checks for keys by default when used with dictionaries, not values. This is a common source of bugs, as you might intuitively expect it to search through everything.

  • If you need to confirm whether a value exists in a dictionary, you must explicitly check against the dictionary's values using the .values() method, like my_value in my_dict.values().

Confusing substring matches with word matches

The in operator finds substrings anywhere, not just whole words. This means a check like 'art' in 'starting' will return True, which might not be what you intend.

  • If you need to find a specific word, a better approach is to split the string into a list of words using the .split() method. Then, you can use the in operator to check for membership in the resulting list.

Forgetting case sensitivity when using in with strings

It's a common pitfall to forget that the in operator is case-sensitive with strings. This isn't just for substrings; it also affects membership checks in lists of strings, which can cause your logic to fail unexpectedly. See what happens below.

user_input = "python"
programming_languages = ["Python", "Java", "JavaScript"]
if user_input in programming_languages:
   print(f"{user_input} is a supported language")
else:
   print(f"{user_input} is not supported")

The check fails because the lowercase string 'python' doesn't exactly match the capitalized 'Python' in the list, leading to an incorrect output. The following example shows how to get the expected result.

user_input = "python"
programming_languages = ["Python", "Java", "JavaScript"]
if user_input.lower() in [lang.lower() for lang in programming_languages]:
   print(f"{user_input} is a supported language")
else:
   print(f"{user_input} is not supported")

The fix ensures a reliable, case-insensitive check. It works by converting both the user_input and the list items to a consistent case using the .lower() method before the comparison. This way, 'python' correctly matches 'Python'.

  • This technique is especially useful when validating user input, since you can't predict the capitalization people will use.

Incorrect value checking with in and dictionaries

A frequent error with dictionaries is using the in operator to find a value. By default, it only checks keys, which can cause your logic to fail unexpectedly. The following example shows what happens when you search for a value directly.

user_data = {"alice": 29, "bob": 35, "charlie": 42}
if 35 in user_data:
   print("Found the age 35")
else:
   print("Age 35 not found")

The expression 35 in user_data returns False because the in operator only checks the dictionary's keys: 'alice', 'bob', and 'charlie'. The following example shows how to correctly search for a value.

user_data = {"alice": 29, "bob": 35, "charlie": 42}
if 35 in user_data.values():
   print("Found the age 35")
else:
   print("Age 35 not found")

The fix is to explicitly search the dictionary's values. The expression 35 in user_data.values() correctly returns True because the .values() method provides a view of all values for the in operator to check. This is the proper way to confirm if a value exists.

  • Remember this technique when you need to find data in a dictionary without knowing its corresponding key.

Confusing substring matches with word matches

It's a common mistake to assume the in operator searches for whole words. It actually looks for substrings, which means it can find a sequence of characters inside a larger word, leading to unexpected results. This can cause subtle bugs.

The following code demonstrates this problem.

text = "The Python programming language is powerful"
if "on" in text:
   print("The text contains 'on'")

The expression 'on' in text returns True because the substring is found within "Python", which can cause false positives. The following example shows how to search for whole words and avoid this problem.

text = "The Python programming language is powerful"
words = text.split()
if "on" in words:
   print("The text contains the word 'on'")
else:
   print("The text does not contain the word 'on'")

The fix is to first split the string into a list of words with the .split() method. When you use the in operator on this new list, it checks for whole words instead of substrings. This is how you avoid false positives, like finding 'on' inside 'Python'.

  • This technique is essential when your logic depends on matching exact words, not just parts of them.

Real-world applications

Now that you can navigate its common pitfalls, you can apply the in operator to solve practical, everyday programming challenges.

Using in for email domain validation

You can create a simple email domain validator by using the in operator to check if the domain part of an email exists in a list of allowed domains.

def is_valid_email_domain(email, allowed_domains):
   domain = email.split('@')[-1]
   return domain in allowed_domains

allowed_domains = ["gmail.com", "yahoo.com", "outlook.com"]
print(is_valid_email_domain("[email protected]", allowed_domains))
print(is_valid_email_domain("[email protected]", allowed_domains))

The is_valid_email_domain function first isolates the domain from an email string. It accomplishes this with email.split('@')[-1], which splits the string at the @ symbol and takes the last part. The function then returns the boolean result of the membership check.

  • The first call returns True because the extracted domain, "gmail.com", is found in the allowed_domains list.
  • The second call returns False since "hotmail.com" is not present in the list.

Finding patterns in log files with in

You can use the in operator to efficiently scan log files and pull out lines containing specific keywords, such as "ERROR" or "CRITICAL".

def extract_critical_logs(log_lines):
   critical_keywords = ["ERROR", "CRITICAL", "FAILURE"]
   return [line for line in log_lines if any(keyword in line for keyword in critical_keywords)]

logs = [
   "2023-09-01 INFO: Service started",
   "2023-09-01 ERROR: Database connection failed",
   "2023-09-01 CRITICAL: System shutdown"
]

for critical_log in extract_critical_logs(logs):
   print(critical_log)

The extract_critical_logs function uses a list comprehension to create a new list of important log entries. It’s a concise way to filter the original logs without a traditional loop.

  • The core of the filter is the any() function. For each line, it checks if any of the strings in critical_keywords exist within that line.
  • This check is done using the in operator, which performs a substring search.
  • If any() finds at least one match, the entire line is included in the new list, which is then returned and printed.

Get started with Replit

Turn your knowledge of the in operator into a real tool. Tell Replit Agent: "Build a script that checks if a username is already taken" or "Create a validator for coupon codes from a list".

The agent writes the code, tests for errors, and deploys your application. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.