Skip to main content

The Many Powers of `in` in Python

🧠 The Many Powers of in in Python

Some syntax is pure gold once you realize how far it stretches.
Python’s in is one of those.

if x in y:

It’s doing search, existence check, branching, and even iteration fallback — all in a single, expressive line.


📜 My Background (Why I Missed This for Years)

I only really dabbled with Python around 2015–2016 — before my first job in the industry. My real "apprenticeship" happened in the .NET ecosystem, but it started with a project I was trying to build in VBA.

That quickly led me to VB — which felt like a better fit — but it didn’t take long to realize that VB was the red-headed stepchild of .NET. The original project was eventually abandoned, but by then the direction was clear: C# FTW.

So I dove in.

C# was flexible — I could build web apps, games with Unity, CLI tools, GUIs (winforms & Xamarin) — and working at a .NET shop with SQL Server everywhere, it made perfect sense to go deep.

I grinded through every lesson I could find, practiced fundamentals, debugged constantly, and built small apps for fun. That’s where I really learned to program.

So back then (and honestly, until about five minutes ago), I mentally sorted loops into two categories:

  1. Trad for loops (C-style):

    for (int i = 0; i < arr.Length; i++)
  2. Collection-based loops:

    foreach (var item in collection)

(Ignoring iterators, generators, lambdas, ES6-style stuff — just talking about the basics here.)

That mental model stuck — across JavaScript, Go, C++, whatever. Index-based loops vs. collection loops. That’s how I saw it. Especially because in most languages, iteration logic lives in the type — through methods or overrides.

So even after using Python daily for over a year, I’d still mentally slotted in into category #2 — “just” a loop keyword.

for item in arr:  # <- Oh cool, it's just a foreach

I didn’t realize that in was more than just syntactic sugar for iteration. I didn’t realize that in could be used anywhere, not just in for loops.

So:

if item in arr:

Looked weird to me at first. I was like — wait, are we looping again?

Nope.


🤯 What I Eventually Realized

Python’s in isn’t just part of the loop syntax. It’s a true operator — one that works on:

  • Lists, tuples, sets
  • Strings
  • Dictionaries (keys only)
  • Even custom classes (if they implement __contains__())

It’s one of the most overloaded and powerful words in the language — but it reads like natural language.

And once you embrace that, your code gets cleaner, shorter, and way more expressive.

Now for some common use cases


✅ Use Case 1: Lists, Tuples, Sets

Let’s start simple:

if 42 in [1, 2, 42]:
print("Found it!")

This works with:

  • list
  • tuple
  • set ← and this one’s O(1) lookup on average

Once you’re doing Leetcode or interview problems, this becomes your best friend for things like deduplication, skipping visited nodes, or fast containment checks.

seen = set()
for val in nums:
if val in seen:
continue
seen.add(val)

Without in, you'd be fumbling with indexes or nested loops. This just reads like logic.


✅ Use Case 2: Strings

Strings are sequences too — so you can use in like a substring check:

if "cat" in "concatenate":
print("Substring match!")

Way cleaner than writing your own substring logic or importing regex for simple tasks.

Also useful in filters:

words = ["calendar", "carpet", "dog"]
filtered = [w for w in words if "ca" in w]

✅ Use Case 3: Dictionaries

Here’s an important point: in only checks keys, not values — at least when used directly on a dict. (See below for how to check values.)

d = {"a": 1, "b": 2}

"a" in d # ✅ True
1 in d # ❌ False
1 in d.values() # ✅ True

This makes in perfect for safely reading from a dict when you only want to do something if the key is present:

if key in data:
do_something()

If you want to check values instead of keys, use:

if i in d.values():
do_something()

It's easier to read than writing a full loop, and quicker to implement than creating a helper function just to return a boolean.

Yes, it's O(n)

It trades a bit of performance for clarity and speed of thought — which is almost always the right move when doing leetcode.

and of course for looping with both key and value you have for k,v in d.items():


✅ Use Case 4: Building Hashmaps (Manual Counting)

This is the one that made me write this whole article. I was building a frequency map manually and wrote this:

if not keyExists(i):
counts[i] = 1

Then I fixed it later with:

if i not in counts:
counts[i] = 1
else:
counts[i] += 1

Totally valid. Totally idiomatic. And my initial pseudo-call (keyExists) was a perfect placeholder because in does exactly that — no helper needed.


✅ Use Case 5: Custom Classes

You can make your own classes support in by defining __contains__():

class WeirdSet:
def __contains__(self, item):
return item == 7

print(7 in WeirdSet()) # True
print(3 in WeirdSet()) # False

This is rare for most daily programming, but good to know if you ever design APIs that feel “Pythonic.”


🧠 Bonus: in in List Comprehensions

You’ll see in pop up all over Python list/set/dict comprehensions:

squares_of_odds = [x*x for x in nums if x % 2 != 0 and x not in seen]

It’s not just doing the iteration — it's doing containment logic inline.


🧩 Summary: in Is More Than a Loop

If you come from C-style languages, it’s easy to think of in as just a syntactic loop helper.

But in Python, in is a logic operator.

  • It checks membership
  • It reads like English
  • It saves boilerplate
  • And it works across almost every built-in type

Once you stop thinking of in as “part of the loop syntax” and start thinking of it as a general-purpose conditional, your Python gets way cleaner — and your logic gets way easier to follow.