文字列の先頭や末尾が特定の文字列と一致するかを判定する処理は、ファイル拡張子やURLチェックなど実務で頻出します。
本記事ではPythonのstr.startswith
とstr.endswith
の使い方を、基本から現場で役立つコツまで段階的に解説します。
空文字との関係や大文字小文字の無視、範囲指定や複数候補の同時判定など、つまずきやすいポイントも丁寧に補足します。
先頭・末尾判定の基本(Python)
文字列の先頭/末尾を判定するメソッド(startswith, endswith)
Pythonの文字列は、先頭一致判定にstartswith
、末尾一致判定にendswith
を備えています。
どちらも対象となる文字列(プレフィックス/サフィックス)
を受け取り、一致すればTrue
、一致しなければFalse
を返します。
特に複数候補をまとめて判定できるタプル指定と、一部範囲だけを対象にするstart
/end
引数がポイントです。
返り値の型と基本ルール(”は常にTrue)
返り値はブール型bool
です。
Pythonでは空文字''
はあらゆる文字列の先頭かつ末尾に存在するというルールがあり、以下はすべてTrue
になります。
逆に、()
(空タプル)を渡した場合は一致候補が無いためFalse
です。
# 基本ルールの確認
s1 = "Python"
s2 = ""
print(s1.startswith("")) # 空文字は常に先頭一致
print(s1.endswith("")) # 空文字は常に末尾一致
print(s2.startswith("")) # 空文字列に対しても同様
print(s2.endswith(""))
# 空タプルは候補が無いのでFalse
print(s1.startswith(()))
print(s1.endswith(()))
True
True
True
True
False
False
以下はstartswith
/endswith
のインターフェイス要点です。
- 書式:
str.startswith(prefix[, start[, end]])
/str.endswith(suffix[, start[, end]])
prefix/suffix
: 文字列、または文字列タプルstart
/end
: スライス同様に[start:end]
の範囲で判定(終端は非包含)
表に主要ルールをまとめます。
観点 | ルール |
---|---|
返り値 | bool |
空文字'' | 先頭/末尾ともに常にTrue |
複数候補 | タプルのみ可。リストは不可 |
空タプル() | 一致候補なしのためFalse |
範囲指定 | start 含む、end は含まない |
大文字小文字無視 | メソッド引数では不可。casefold() 等で事前変換 |
- 関連記事:文字列の長さを調べる
startswithで先頭を判定する
基本構文とサンプルコード
startswith
は文字列が特定の接頭辞で始まるかを判定します。
可読性が高く、スライス比較より意図が明確です。
# startswith の基本
lang = "Python 3.12"
print(lang.startswith("Py")) # "Py"で始まるか
print(lang.startswith("Python")) # 完全一致の先頭
print(lang.startswith("Java")) # 不一致
True
True
False
複数パターンをまとめて判定する(tuple)
複数の接頭辞候補がある場合はタプル
でまとめられます。
リストは使用不可で、TypeError
になります。
# 複数候補をタプルで
name = "readme.txt"
print(name.startswith(("read", "doc", "note"))) # いずれかに一致すればTrue
# リストを渡すとTypeError
try:
print(name.startswith(["read", "doc"]))
except TypeError as e:
print(f"Error: {e}")
True
Error: startswith first arg must be str or a tuple of str, not list
一部だけを判定する(start/end引数)
start
/end
はスライスと同じ意味で、対象範囲を限定できます。
# 範囲を限定して先頭一致を判定
text = "HelloWorld"
# インデックス5からの部分文字列は "World"
print(text.startswith("World", 5)) # True
# 0〜5の範囲("Hello")の中で"Hel"で始まるか
print(text.startswith("Hel", 0, 5)) # True
# endは非包含。0〜4("Hell")には"Hello"は収まらない
print(text.startswith("Hello", 0, 4)) # False
True
True
False
大文字小文字を無視して判定する(casefold)
startswith
自体に大文字小文字を無視するオプションはありません。
文字列同士をcasefold()
で正規化してから判定します。
lower()
よりcasefold()
のほうが国際化対応として望ましいです。
# 大文字小文字を無視した先頭一致
s = "Straße in Berlin" # ß を含む
prefix = "STRASSE" # 大文字
print(s.casefold().startswith(prefix.casefold())) # True
# 複数候補にも対応する小ヘルパー
def startswith_icase(s: str, prefixes) -> bool:
if isinstance(prefixes, tuple):
folded = tuple(p.casefold() for p in prefixes)
return s.casefold().startswith(folded)
return s.casefold().startswith(prefixes.casefold())
print(startswith_icase("Hello", ("he", "yo"))) # True
print(startswith_icase("data.csv", ("JSON", "CSV"))) # False
True
True
False
endswithで末尾を判定する
基本構文とサンプルコード
endswith
は文字列が特定の接尾辞で終わるかを判定します。
ファイル拡張子のチェックなどで多用します。
# endswith の基本
path = "archive.tar.gz"
print(path.endswith(".gz")) # True
print(path.endswith(".zip")) # False
True
False
複数パターンをまとめて判定する(tuple)
複数の拡張子や接尾辞をまとめてチェックできます。
filename = "report.final.pdf"
# 複数拡張子に対応
print(filename.endswith((".pdf", ".docx", ".xlsx"))) # True
# 空タプルはFalse
print(filename.endswith(())) # False
True
False
一部だけを判定する(start/end引数)
末尾判定でもstart
/end
で範囲を限定できます。
# 範囲を限定して末尾一致
msg = "INFO: job done OK"
# 6〜の部分("job done OK")が"OK"で終わるか
print(msg.endswith("OK", 6)) # True
# 6〜14("job done")は"OK"で終わらない
print(msg.endswith("OK", 6, 14)) # False
True
False
大文字小文字を無視して判定する(casefold)
こちらもcasefold()
で正規化してから判定します。
# 大文字小文字を無視した末尾一致
s = "README.TXT"
print(s.casefold().endswith(".txt")) # ".txt"をそのまま小文字で渡してもOK
# 複数候補
def endswith_icase(s: str, suffixes) -> bool:
if isinstance(suffixes, tuple):
folded = tuple(x.casefold() for x in suffixes)
return s.casefold().endswith(folded)
return s.casefold().endswith(suffixes.casefold())
print(endswith_icase("photo.JPEG", (".jpg", ".jpeg", ".png"))) # True
True
True
よくある用途と注意点
ファイル拡張子チェックに使う(.txtや.csv)
拡張子のように「末尾が特定の文字列か」を確認する処理ではendswith
が最適です。
複数拡張子をまとめて許容する場合はタプル指定にすることで、分岐を増やさずに書けます。
大小文字を無視したいときはcasefold()
を使います。
files = ["data.csv", "image.PNG", "readme.md", "report.CSV"]
allow = (".csv", ".tsv")
for f in files:
if f.casefold().endswith(tuple(ext.casefold() for ext in allow)):
print(f"tabular: {f}")
else:
print(f"skip: {f}")
tabular: data.csv
skip: image.PNG
skip: readme.md
tabular: report.CSV
複合拡張子.tar.gz
なども、(".gz", ".bz2")
のようにまとめれば対応できます。
パス解析が必要なら別記事で扱うpathlib
の利用も検討してください。
URLのスキームやドメインで判定(http, https)
URLのスキーム確認にはstartswith(("http://", "https://"))
が読みやすいです。
ドメイン末尾のTLD判定にはendswith((".com", ".co.jp"))
が使えます。
ただしフィッシング対策など厳密な検証が必要な場合は、ドット区切りやポート、パスの検証を含めたパーサの利用をおすすめします。
urls = ["https://example.com", "http://localhost:8000", "ftp://files.example.org"]
for u in urls:
if u.startswith(("http://", "https://")):
print(f"web: {u}")
else:
print(f"skip: {u}")
web: https://example.com
web: http://localhost:8000
skip: ftp://files.example.org
スライス比較よりstartswith/endswithが可読的
s[:3] == "abc"
のようなスライス比較でも先頭判定は可能ですが、startswith
/endswith
は「何をしたいか」が直感的で、複数候補や範囲指定も一貫した書式で表現できます。
また、スライスは自分で長さを数える必要があり、意図が曖昧になりがちです。
s = "abcXYZ"
# 可読性の比較
print(s.startswith("abc")) # 意図が明確
print(s[:3] == "abc") # 動作は同じだが意図がやや不透明
True
True
複数条件はtupleのみ(listは不可)
候補の並びをlist
で渡すとTypeError
になります。
忘れずにtuple
を使ってください。
tuple([...])
で変換しても構いません。
candidates = ["pre", "head"]
s = "prefix"
try:
print(s.startswith(candidates)) # NG
except TypeError:
print(s.startswith(tuple(candidates))) # OKにしてから実行
True
空白や改行が混ざる場合の前処理の考え方
入力値の前後に空白や改行が混ざると意図せぬ不一致になります。
判定前にstrip()
やlstrip()
/rstrip()
で前処理すると堅牢です。
全角空白や特殊空白が来る可能性がある場合は、追加の正規化(例えばunicodedata.normalize
の活用)も検討してください。
raw = " hello.txt \n"
clean = raw.strip() # 前後の空白と改行を除去
print(clean.endswith(".txt")) # True
True
正規表現を使うべきケースとの使い分け(re)
startswith
/endswith
は固定の接頭辞・接尾辞に最適です。
一方でワイルドカードや桁数条件、文字クラスなど可変条件が必要な場合はre
を使います。
先頭/末尾は^
/$
で表現できます。
import re
s1 = "USER-12345"
s2 = "user_987"
# "USER-"で始まり、後に数字が続く
print(bool(re.match(r"^USER-\d+$", s1))) # True
# 先頭は"USER-"ではないのでFalse
print(bool(re.match(r"^USER-\d+$", s2))) # False
# 大文字小文字を無視
print(bool(re.match(r"^user_\d+$", s2, flags=re.IGNORECASE))) # True
True
False
True
使い分けの目安として、固定の「始まる/終わる」だけならstartswith
/endswith
、パターンが複雑ならre
と覚えると良いでしょう。
- 関連記事:正規表現(re)入門
まとめ
本記事では、文字列のstartswith
とendswith
の基本から応用までを解説しました。
空文字は常に一致、複数候補はタプルのみ、範囲は[start:end]
、大文字小文字はcasefold()
で正規化という要点を押さえれば、多くの場面で迷わず書けます。
拡張子やURLスキームのチェック、前処理としてのstrip()
、複雑な条件ではre
といった使い分けを意識し、意図が伝わる可読的なコードを心がけてください。