閉じる

Pythonのcount()で文字列内の特定の文字数を数える方法

Pythonの文字列メソッドcount()は、文字やサブ文字列が何回現れるかを効率よく数えるための基本ツールです。

本記事では初心者がつまずきやすい範囲指定や大小文字、Unicodeの表記ゆれまで丁寧に解説し、すぐ使えるサンプルコードと出力を示しながら理解を深めます。

Pythonのstr.count()の基本

count()で文字列中の出現回数を数える

count()は対象の文字列に対して呼び出し、引数で指定した文字やサブ文字列の出現回数を返します。

まずは最小の例から確認します。

Python
# 基本: "banana" に含まれる "a" の数を数える
s = "banana"
result = s.count("a")
print(result)  # 期待: 3
実行結果
3

戻り値は整数で、見つかった回数を返します

また、count()は非破壊的です。元の文字列sは変化しません。

文字(1文字)とサブ文字列の両方を数えられる

count()は1文字だけでなく、複数文字からなるサブ文字列にも使えます。

Python
s = "bananana"
print(s.count("a"))    # "a" の数
print(s.count("na"))   # "na" の数
print(s.count("nana")) # "nana" の数
実行結果
4
3
2

1文字でも複数文字でも同じメソッドで扱える点が便利です。

見つからない場合は0になる

対象が見つからない場合は常に0になります。

例外にはなりません。

Python
s = "banana"
print(s.count("z"))     # "z" は存在しない
print(s.count("xyz"))   # "xyz" も存在しない
実行結果
0
0

count()の引数と範囲指定

引数(sub, start, end)の意味

count()のシグネチャはstr.count(sub[, start[, end]])です。

  • sub: 数えたい文字またはサブ文字列
  • start: 探索開始位置のインデックス(省略可)
  • end: 探索終了位置のインデックスの直前まで(省略可)

範囲はスライスと同じ半開区間[start, end)で、end自体は含みません

以下の表は各引数の要点をまとめたものです。

引数既定値説明
substrなし数える対象の文字列
startint0探索開始位置(含む)
endintlen(s)探索終了位置(含まない)
Python
s = "abracadabra"
# 文字列全体を対象に "a" を数える
print(s.count("a"))

# インデックス2から末尾直前までの範囲で "a" を数える
print(s.count("a", 2))

# インデックス2以上、8未満の範囲で "a" を数える
print(s.count("a", 2, 8))
実行結果
5
4
3

よくある勘違い

endは含まれません

たとえばcount("a", 2, 8)はインデックス8の位置は対象外です。

部分範囲を指定して数える(startとend)

部分的に数えたい場合、startendを使います。

文中の特定セクションだけを数えるのに有用です。

Python
text = "Header\nbody line 1\nbody line 2\nFooter"
# 本文部分("body..."が始まる位置以降)だけで "o" を数える
start = text.index("body")  # "body" の開始位置
end = text.rindex("\n")     # 最後の改行の位置(ここは含まれない)
print(text.count("o", start, end))
実行結果
2

end = text.rindex("\n")にて最終行が除外されるようになっているので、最後のFooteroはカウントされず、2個となります。

負のインデックスで末尾から範囲指定

インデックスは負の値も使え、末尾からの相対位置を指定できます。

Python
s = "2024-09-10"
# 末尾5文字(例: "-10")の範囲で "-" を数える
print(s.count("-", -5))          # start=-5 から末尾まで
# 末尾8文字の範囲[-8, -3)で "-" を数える
print(s.count("-", -8, -3))      # end は含まれないことに注意
実行結果
1
1

スライスとcount()の組み合わせ

スライスで切り出した部分に対してcount()を呼ぶ方法も直感的です。

Python
s = "prefix[MIDDLE]suffix"
middle = s[s.index("[")+1 : s.index("]")]
print(middle)          # "MIDDLE"
print(middle.count("D"))
実行結果
MIDDLE
2

スライスは読みやすさの向上にも役立ちます

具体例で学ぶcount()の使い方

特定の文字数を数える(改行・空白・記号)

ログやテキスト整形では、改行や空白、区切り記号の数を数える場面が多いです。

Python
log = "INFO Start\nWARN Disk low\nERROR Failed\nINFO End\n"
# 改行の数
nl = log.count("\n")
# 半角スペースの数
spaces = log.count(" ")
# コロン ":" の数
colons = log.count(":")

print("newlines:", nl)
print("spaces:", spaces)
print("colons:", colons)
実行結果
newlines: 4
spaces: 5
colons: 0

改行は可視化されない文字なので、明示的に”\n”を数えると確実です。

サブ文字列の出現回数を数える(単語や拡張子)

単語や拡張子の出現回数を知りたいときにも使えます。

Python
text = "cat scatter catalog concatenate cat"
# "cat" は単語境界を問わず数えるので "scatter" や "catalog" 内も含む
print(text.count("cat"))

files = "a.png b.jpg c.png d.PNG e.png"
# 拡張子 ".png" の出現数(大小文字は区別される点に注意)
print(files.count(".png"))
実行結果
5
3

単語境界を考慮したい場合は正規表現など別手段が必要です。

CSVのカンマ数やURLのスラッシュ数を数える

CSV行の列数はカンマ数+1で見積もれます。

URLの階層をスラッシュで概観することもできます。

Python
csv_line = "id,name,age,email,city"
commas = csv_line.count(",")
columns_estimate = commas + 1  # 簡易見積もり

url = "https://example.com/path/to/resource/"
slashes = url.count("/")

print("commas:", commas)
print("columns (approx):", columns_estimate)
print("slashes:", slashes)
実行結果
commas: 4
columns (approx): 5
slashes: 6

CSVの厳密な列数は引用符やエスケープに左右されます

ここでは簡易な見積もりとして活用します。

大文字小文字をそろえてから数える(ケース差への対応)

count()は大小文字を区別します。

事前にlower()casefold()で正規化すると意図どおりに数えられます。

Python
text = "Apple, APPLE, apple, ApPlE"
target = "apple"

# そのまま数える(大小文字を区別)
print(text.count(target))  # 1

# 小文字化してから数える
print(text.lower().count(target))  # 4

# より包括的な大小文字正規化(casefold)
print(text.casefold().count(target))  # 4
実行結果
1
4
4

国際化対応ではcasefold()がより堅牢です。

count()の注意点とベストプラクティス

重なり合う出現は数えない(aa中のaaは1件)

count()重なり合う一致を数えません

Python
s = "aaaa"
print(s.count("aa"))  # "aa" は [0:2], [2:4] の2回。重なり(1:3)は数えない
実行結果
2

オーバーラップを数えたい場合は別実装が必要です。

参考: オーバーラップを数える単純実装

Python
def count_overlapping(s: str, sub: str) -> int:
    # 1文字ずつずらして一致するたびに数える
    if not sub:
        return len(s) + 1  # Pythonの仕様に合わせる
    c = 0
    i = 0
    while True:
        i = s.find(sub, i)
        if i == -1:
            return c
        c += 1
        i += 1  # 1文字進めることでオーバーラップも検出
print(count_overlapping("aaaa", "aa"))
実行結果
3

空文字はlen(s)+1になる

subに空文字""を渡すと、文字列の「隙間」の数であるlen(s)+1が返ります。

Python
s = "abc"
print(len(s), s.count(""))
実行結果
3 4

仕様として正しい挙動ですが、多くの場合は意図しないので注意します。

大文字小文字は区別される

デフォルトでは区別ありです。

必要に応じて前処理しましょう。

Python
s = "Hello HELLO HeLLo"
print(s.count("hello"))          # 0
print(s.lower().count("hello"))  # 3
実行結果
0
3

全角/半角や結合文字は別扱い(Unicodeの表記ゆれ)

見た目が同じでも、内部表現が違うと一致しません。

例として結合文字を含むケースを示します。

Python
import unicodedata

# 見た目は "é" だが2通りの表現がある
composed = "é"           # U+00E9
decomposed = "e\u0301"   # "e" + 結合アクセント(U+0301)

s = composed * 3
print("raw count:", s.count(decomposed))  # 0 になる

# 正規化(NFC/NFD)を揃えてから数える
s_nfc = unicodedata.normalize("NFC", s)
sub_nfc = unicodedata.normalize("NFC", decomposed)
print("NFC count:", s_nfc.count(sub_nfc))
実行結果
raw count: 0
NFC count: 3

Unicode正規化を揃えるのが堅実です。

全角/半角の違いも別文字として扱われます。

正規表現は使えない(パターン一致は対象外)

count()は固定の文字列一致のみです。

パターンや単語境界を扱うにはreモジュールなどを使います。

Python
import re

text = "cat scatter catalog concatenate cat"
# 単語としての "cat" のみ数える(単語境界 \b を利用)
matches = re.findall(r"\bcat\b", text)
print(len(matches))
実行結果
2

大きな文字列では一度だけ数えるようにする(効率化)

巨大な文字列に対して同じcount()を何度も呼ぶと無駄な走査が増えます。

結果を変数に保持し、必要に応じて再利用しましょう。

Python
s = "log entry;" * 1_000_00  # デモ用の大きめ文字列
# 悪い例: 同じ計算を繰り返す
a = s.count(";")
b = s.count(";")
c = s.count(";")

# 良い例: 1回だけ計算して使い回す
count_semicolon = s.count(";")
print(a == b == c == count_semicolon)
実行結果
True

事前の前処理(例: lower/casefoldや正規化)を1回で済ませてからcountするのも効果的です。

まとめ

str.count()は文字列内の出現回数を素早く数えるための基本メソッドで、単純一致・範囲指定・負のインデックス・スライスとの併用まで押さえれば多くの用途をカバーできます。

注意点として重なり合いは数えない空文字はlen(s)+1大小文字やUnicodeの表記ゆれは一致しないことを理解し、必要に応じてlower()casefold()unicodedata.normalize()の前処理を取り入れると良いです。

さらに、大きな文字列では同じ数え上げを繰り返さないなどの効率化も意識しましょう。

これらのポイントを押さえれば、改行や空白、区切り記号、拡張子やURLの構造把握など、実務で頻出のカウント作業を確実にこなせます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!