.count Python: How to Count Occurrences in Lists, Strings, and Tuples
When you need to answer the question “how many times does this value appear?”, Python gives you a small, fast tool built right into its core types: the `.count()` method. It exists on lists, strings, and tuples, and it does exactly one thing — it scans the sequence and tells you how many times a specific value shows up. No imports, no loops, no boilerplate.
But `.count()` is also one of the most quietly misused methods in Python. People reach for it when they should reach for `collections.Counter`, they trip over the overlapping-substring rule on strings, and they confuse it with `len()`. This guide walks through every correct use of `.count()` with runnable code and output, then shows you exactly when to stop using it.
Key Takeaways
• `.count(value)` returns how many times `value` appears in a list, tuple, or string — it answers one targeted question.
• On strings, `str.count(sub)` counts non-overlapping occurrences and accepts optional `start`/`end` bounds.
• The classic gotcha: `’aaa’.count(‘aa’)` is `1`, not `2`, because matches don’t overlap.
• `.count()` only matches exact values; for conditions use `sum(1 for x in items if cond)`.
• Need the frequency of *every* value, not just one? Use `collections.Counter` — one pass instead of many.
• `len()` gives the total number of items; `.count()` gives occurrences of one value.
What does the .count() method do in Python?
The `.count()` method returns an integer: the number of times a given value occurs in a sequence. It is available on Python’s built-in sequence types — `list`, `tuple`, and `str` — and it always performs a left-to-right scan of the whole sequence.
“`python numbers = [1, 2, 2, 3, 2, 4] print(numbers.count(2)) “`
“`text 3 “`
The value `2` appears three times, so `.count(2)` returns `3`. If the value is not present at all, you get `0` rather than an error:
“`python print([1, 2, 3].count(99)) “`
“`text 0 “`
That “zero, not error” behavior makes `.count()` safe to call without checking membership first.
How do you use .count() on a list?
For lists, the signature is `list.count(x)`. It compares each element to `x` using equality (`==`) and tallies the matches.
“`python fruits = [“apple”, “banana”, “apple”, “cherry”, “apple”, “banana”]
print(fruits.count(“apple”)) # how many apples? print(fruits.count(“banana”)) # how many bananas? print(fruits.count(“grape”)) # not in the list “`
“`text 3 2 0 “`
Because it uses `==`, it works with any comparable objects — numbers, strings, tuples, even nested lists:
“`python points = [(0, 0), (1, 1), (0, 0), (2, 3)] print(points.count((0, 0))) “`
“`text 2 “`
For more on the data structure itself, see .
How does .count() work on strings?
On strings, the method counts how many times a substring appears. The signature is `str.count(sub)`, and it can match single characters or multi-character substrings.
“`python text = “mississippi”
print(text.count(“s”)) # single character print(text.count(“ss”)) # substring print(text.count(“z”)) # absent “`
“`text 4 2 0 “`
What makes the string version more powerful than the list version is the optional `start` and `end` arguments: `str.count(sub, start, end)`. These let you restrict the count to a slice of the string without actually creating a new substring.
“`python sentence = “the cat sat on the mat”
print(sentence.count(“at”)) # whole string print(sentence.count(“at”, 8)) # from index 8 to the end print(sentence.count(“the”, 0, 10)) # only within the first 10 chars “`
“`text 3 2 1 “`
The `start` and `end` bounds behave just like slice indices: `start` is inclusive, `end` is exclusive. This is handy when you only care about part of a larger block of text. If you work with text a lot, is worth a read.
Does .count() work on tuples?
Yes. Tuples are sequences too, and `tuple.count(x)` behaves exactly like the list version — exact-value matching with `==`.
“`python schedule = (“mon”, “tue”, “mon”, “wed”, “mon”, “fri”) print(schedule.count(“mon”)) “`
“`text 3 “`
Since tuples are immutable, `.count()` is one of only two methods they expose (the other being `.index()`). It is the natural way to ask “how many times does this value appear in my fixed sequence?”
Here is a quick reference for what each call returns across types:
| Call | Returns |
|---|---|
| `[1, 2, 2, 3].count(2)` | `2` |
| `[1, 2, 3].count(9)` | `0` |
| `”banana”.count(“a”)` | `3` |
| `”banana”.count(“an”)` | `2` |
| `”aaaa”.count(“aa”)` | `2` (non-overlapping) |
| `”abcabc”.count(“bc”, 3)` | `1` (search from index 3) |
| `(“x”, “y”, “x”).count(“x”)` | `2` |
Why is ‘aaa’.count(‘aa’) equal to 1 and not 2?
This is the single most common surprise with `str.count()`. Matches do not overlap. After Python finds a match, it continues searching *from the end of that match*, not from the next character.
“`python print(“aaa”.count(“aa”)) print(“aaaa”.count(“aa”)) print(“aaaaa”.count(“aa”)) “`
“`text 1 2 2 “`
Walk through `”aaa”.count(“aa”)`: Python matches `”aa”` at index 0, then resumes searching at index 2. Only `”a”` remains, which can’t match `”aa”`, so the final count is `1`. The third overlapping `”aa”` (indices 1–2) is never counted.
If you genuinely need overlapping matches, `.count()` is the wrong tool — you’d write a small sliding-window loop instead:
“`python def count_overlapping(text, sub): count = start = 0 while True: i = text.find(sub, start) if i == -1: return count count += 1 start = i + 1 # advance by ONE, not by len(sub)
print(count_overlapping(“aaa”, “aa”)) “`
“`text 2 “`
How do you count items that match a condition?
`.count()` has a hard limit: it only matches exact values. You cannot ask it “how many numbers are greater than 10?” or “how many strings are longer than 5 characters?” For conditional counting, use a generator expression with `sum()`:
“`python numbers = [4, 17, 3, 25, 8, 42, 1]
big = sum(1 for n in numbers if n > 10) print(big)
words = [“hi”, “hello”, “hey”, “greetings”, “yo”] long_words = sum(1 for w in words if len(w) > 3) print(long_words) “`
“`text 3 2 “`
The pattern `sum(1 for x in items if condition)` is the idiomatic Python way to count by a predicate. It reads almost like English and runs in a single pass. Reach for it whenever your question is “how many items satisfy *this rule?*” rather than “how many items equal *this value?*”
How do you count every value at once with collections.Counter?
When you need the frequency of *many* values — or all of them — `.count()` is the wrong tool. The right tool is `collections.Counter`, a dictionary subclass purpose-built for tallying.
“`python from collections import Counter
votes = [“red”, “blue”, “red”, “green”, “blue”, “red”, “blue”] tally = Counter(votes)
print(tally) print(tally[“red”]) # access like a dict print(tally[“yellow”]) # missing keys return 0, no KeyError “`
“`text Counter({‘red’: 3, ‘blue’: 3, ‘green’: 1}) yellow → 0 “`
“`python print(tally[“yellow”]) “`
“`text 0 “`
`Counter` also gives you ranking for free via `.most_common()`:
“`python from collections import Counter
text = “the quick brown fox the lazy dog the end” word_counts = Counter(text.split())
print(word_counts.most_common(2)) “`
“`text [(‘the’, 3), (‘quick’, 1)] “`
For a deeper dive, see .
Here is the rule that separates clean Python from accidentally slow Python. `list.count()` and `str.count()` are perfect for one question — “how many times does *this specific value* appear?” But developers misuse them by calling `count()` inside a loop to tally many different values, which is quietly O(n²): each `count()` call rescans the *entire* sequence, so counting 100 distinct values means 100 full passes over your data.
“`python
items = [“a”, “b”, “a”, “c”, “b”, “a”] frequency = {} for value in set(items): frequency[value] = items.count(value) # full scan, every time “`
The moment you need the frequency of more than one or two values, stop reaching for `.count()` and reach for `collections.Counter`, which tallies every value in a single pass and hands you a ready dictionary:
“`python from collections import Counter items = [“a”, “b”, “a”, “c”, “b”, “a”] frequency = Counter(items) # one pass, done print(dict(frequency)) “`
“`text {‘a’: 3, ‘b’: 2, ‘c’: 1} “`
The rule: use `.count()` for a single targeted question (“how many 5s are in this list?”); use `Counter` for a full census (“how many of each value?”). Building a frequency table with `.count()` in a loop is the classic accidental-quadratic trap — one `Counter` call does the whole job once.
What is the difference between .count() and len()?
These two are easy to confuse because both return integers about a sequence, but they answer completely different questions:
- `len(seq)` returns the total number of items in the sequence.
- `seq.count(value)` returns how many times one specific value appears.
“`python data = [1, 2, 2, 3, 2]
print(len(data)) # total items print(data.count(2)) # occurrences of the value 2 “`
“`text 5 3 “`
| Question | Use |
|---|---|
| How many items are there in total? | `len(seq)` |
| How many times does value X appear? | `seq.count(X)` |
| How many of *each* value appear? | `Counter(seq)` |
A useful sanity check: `len(data)` should always be greater than or equal to `data.count(anything)`, since the count of any single value can never exceed the total number of items. New to Python types and built-in functions? Start with .
How fast is .count() — what’s the performance cost?
`.count()` runs in O(n) time: it scans the entire sequence from start to finish every single time you call it, regardless of where (or whether) the value appears. One call over a list of a million items touches all million elements.
That cost is perfectly fine for a single question. It becomes a problem when you call `.count()` repeatedly. As shown in the unique-insight section above, a loop of `.count()` calls multiplies into O(n²). `Counter`, by contrast, builds the full frequency map in a single O(n) pass — so if you need more than a couple of counts, it is both faster and clearer.
A simple decision guide:
- One or two specific values? `.count()` is clean and fast enough.
- Many values, or “all of them”? `Counter` — one pass, ready dictionary.
- A condition, not an exact value? `sum(1 for x in items if cond)`.
Run your Python work on infrastructure you control. DarazHost VPS and dedicated servers give developers a real Python environment with full control — process and analyze data efficiently on guaranteed resources with root access. Whether you’re tallying millions of records with `Counter` or running data pipelines that can’t afford a noisy neighbor, it’s the dependable home your Python work needs, backed by 24/7 support. Learn more in our complete guide to hosting for developers.
Frequently Asked Questions
Does Python’s .count() count overlapping substrings? No. `str.count()` counts non-overlapping occurrences. That’s why `’aaa’.count(‘aa’)` returns `1`, not `2` — after matching the first `”aa”`, the search resumes past it. For overlapping matches, use a `find()`-based sliding window that advances by one character at a time.
Can I use .count() with a condition like “greater than 10”? No. `.count()` only matches exact values using `==`. For conditional counting, use a generator expression: `sum(1 for x in items if x > 10)`.
Is .count() the same as len()? No. `len(seq)` returns the total number of items in the sequence; `seq.count(value)` returns how many times one specific value appears. `len(seq)` is always greater than or equal to `seq.count(anything)`.
When should I use collections.Counter instead of .count()? Use `Counter` whenever you need the frequency of more than one or two values. Calling `.count()` in a loop to build a frequency table is O(n²) because each call rescans the whole sequence; `Counter` tallies every value in a single O(n) pass.
Does .count() work on dictionaries or sets? No. `.count()` is a sequence method available only on lists, tuples, and strings. Sets store unique values (so any value’s count is 0 or 1), and dictionaries have unique keys — for tallying you’d build a `Counter` or use `dict.get()` accumulation instead.