文字列を左右に分けたい時、分割した後も区切り文字そのものを残しておきたい場面があります。
Pythonのstr.partition()
は、最初に見つかった区切りで文字列を前・区切り・後の3つに分けられる便利なメソッドです。
本記事では初心者でも段階的に理解できるように、基本から実用例、split()
との違い、注意点まで丁寧に解説します。
Pythonのpartition()の基本(区切り文字を残して3分割)
partition()とは
str.partition(sep)
は、対象の文字列の中からsep(区切り文字列)
を最初に見つけた位置で3分割します。
返り値はタプル(前, 区切り, 後)です。
- 関連記事:タプル(tuple)の基本的な使い方
区切り文字そのものが返り値に含まれる点が特徴です。
最小のイメージ
- 入力: “a=b=c” と “=”
- 出力: (“a”, “=”, “b=c”)
返り値(前, 区切り, 後)の意味
返り値の3要素は次の通りです。
これにより、区切りを保持しつつ柔軟に再構築できます。
- 0番目: 区切りより前の部分文字列
- 1番目: 見つかった区切り文字列(必ず
sep
と同じ) - 2番目: 区切りより後ろの部分文字列
区切りを保ったまま加工できるので、ログ処理や設定解析で重宝します。
区切り文字がない場合の結果
もし区切りが見つからない場合は、区切りと後ろが空文字になります。
つまり(元の文字列, “”, “”)が返ります。
区切り文字は複数文字も可
sep
は1文字に限らず、複数文字でもOKです。
例えば"://"
や"--"
などをそのまま使えます。
- 関連記事:正規表現(re)入門
空の区切り文字は不可(ValueError)
sep=""
はValueErrorになります。
空文字では分割できないため、必ず長さ1以上の文字列を指定してください。
# 基本動作のデモ
s1 = "a=b=c"
print(s1.partition("=")) # 最初の "=" で3分割
s2 = "abc"
print(s2.partition(",")) # 区切りがない
s3 = "scheme://host/path"
print(s3.partition("://")) # 区切りは複数文字でもOK
# 空の区切り文字はエラー
try:
print("x".partition(""))
except ValueError as e:
print("エラー:", type(e).__name__, str(e))
('a', '=', 'b=c')
('abc', '', '')
('scheme', '://', 'host/path')
エラー: ValueError empty separator
- 関連記事:try-exceptで例外処理を実装する
- 関連記事:find()とindex()で文字列を検索する
使い方ステップ(区切り文字を残す3分割)
最初の出現で3分割する基本例
最初に見つかった区切りで分割される点を確かめます。
分割後のタプルから必要な部分だけ取り出せます。
text = "name: Alice: admin"
left, sep, right = text.partition(":") # 最初の ":" で3分割
print(f"left={left!r}, sep={sep!r}, right={right!r}")
left='name', sep=':', right=' Alice: admin'
key=valueを3分割して取り出す
設定行のような"key=value"
形式はpartitionが最適解です。
区切り文字"="
も保持できるため、再構築やロギングもしやすくなります。
config_line = "timeout = 30"
key, eq, value = config_line.partition("=")
# 前後の空白を取り除きつつ、valueを数値にキャスト
key = key.strip()
value = value.strip()
print(key, eq, value, type(value))
value_int = int(value) # "30" -> 30
print("value_int + 1 =", value_int + 1)
timeout = 30 <class 'str'>
value_int + 1 = 31
- 関連記事:設定ファイル(JSON/YAML/INI)を読み書きする方法
- 関連記事:文字列と数値の型を変換したい
ファイル名.拡張子を分ける
拡張子は通常末尾側の最後のピリオドで分けるのが自然です。
ここではrpartition(".")
を使います。
区切りを保持したいので"."
そのものが返ってきます。
filename = "archive.tar.gz"
base, dot, ext = filename.rpartition(".") # 末尾側の "." で3分割
print(base, dot, ext)
# dot が空の場合は拡張子なし
if dot:
print(f"拡張子: .{ext}")
else:
print("拡張子なし")
archive.tar . gz
拡張子: .gz
パス/URLの最初の区切りまでを取得
URLのスキームと残り、パスの先頭フォルダと残りなど、最初の区切りが欲しい時に有効です。
url = "https://example.com/path/to/page"
scheme, sep, rest = url.partition("://")
print("scheme:", scheme, "sep:", sep, "rest:", rest)
path = "users/alice/doc.txt"
head, slash, tail = path.partition("/") # 最初の "/" で3分割
print("head:", head, "slash:", slash, "tail:", tail)
scheme: https sep: :// rest: example.com/path/to/page
head: users slash: / tail: alice/doc.txt
- 関連記事:pathlib入門 Pathでパス結合/走査/存在確認
- 関連記事:CSVを読み込む・書き出す
splitとの違いとrpartition()の使い分け
splitとpartition()の違い(区切りの保持)
split()
は区切りを捨てるのに対し、partition()
は区切りを返り値に含める点が大きな違いです。
分割後に区切りを使ってメッセージを再合成したい場合、partition()
が明快です。
maxsplit=1とpartition()の比較
split(sep, maxsplit=1)
でも2要素に分けられますが、区切りが失われるため、必要なら自分で補う必要があります。
partition()
は最初から3要素で、区切りが第2要素として入っています。
s = "key=value=extra"
# split + maxsplit=1 は2要素(区切りは消える)
parts = s.split("=", maxsplit=1)
print("split:", parts)
# partition は3要素(区切りが保持される)
before, sep, after = s.partition("=")
print("partition:", (before, sep, after))
split: ['key', 'value=extra']
partition: ('key', '=', 'value=extra')
- 関連記事:スライスで文字列の一部を取得する
末尾から分割するならrpartition()
右側(末尾側)から最初に見つかった区切りで分けたい場合はrpartition()
を使います。
拡張子分離や最後の区切りが重要なログ解析で有効です。
log = "2025-09-10 12:00:00 INFO module.sub: message"
left, sep, right = log.rpartition(":") # 右から最初の ":" で分割
print(left)
print(sep)
print(right)
2025-09-10 12:00:00 INFO module.sub
:
message
下表に要点を整理します。
項目 | partition | rpartition | split | 備考 |
---|---|---|---|---|
区切りの保持 | する | する | しない | partition系は区切りを第2要素に返す |
分割方向 | 左から最初 | 右から最初 | 左から(可変) | splitは要素数が可変 |
返り値型 | タプル(3要素) | タプル(3要素) | リスト(要素数可変) | 用途に合わせて選択 |
よくある落とし穴とコツ
区切りが複数回出る場合の扱い
partition()
は最初の1回だけで分割します。
すべての出現箇所で区切りを保持しつつ処理したい場合は、while
で残りを繰り返しpartition()
する手もあります。
s = "a=b=c=d"
sep = "="
parts = []
rest = s
while True:
left, mid, right = rest.partition(sep)
parts.append(left)
if not mid: # 区切りが見つからない
break
parts.append(mid) # 区切りを保持
rest = right
print(parts)
['a', '=', 'b', '=', 'c', '=', 'd']
- 関連記事:ジェネレータの基本と使い方
前後の空白はstripと併用
設定やCSVでは区切りの前後に空白が紛れることがよくあります。
分割後にstrip()
で整形すると堅牢になります。
row = "name , Alice"
key, comma, value = row.partition(",")
key = key.strip()
value = value.strip()
print(key, comma, value)
name , Alice
大文字小文字を無視したい時の手順
partition()
は大文字小文字を区別します。
無視したい場合は、小文字化して位置を探し、元の文字列をスライスします。
text = "Header: Value"
sep = "header:" # 大文字小文字を無視して分けたい
lower_text = text.lower()
lower_sep = sep.lower()
idx = lower_text.find(lower_sep)
if idx != -1:
# 元の文字列から実際の区切り(元の大文字小文字を保持)を抜き出す
real_sep = text[idx:idx + len(sep)]
before = text[:idx]
after = text[idx + len(sep):]
print((before, real_sep, after))
else:
print((text, "", ""))
('', 'Header:', ' Value')
非文字列には使えない点に注意
partition()
は文字列メソッドです。
数値やNone
、リストには使えません。
必要に応じてstr()
で文字列化してから使います。
value = 12345
try:
# 数値には partition が存在しない
value.partition("3") # AttributeError
except AttributeError as e:
print("AttributeError:", e)
# 文字列化すれば使える
s = str(value)
print(s.partition("3"))
AttributeError: 'int' object has no attribute 'partition'
('12', '3', '45')
- 関連記事:リスト(list)の使い方
まとめ
区切り文字そのものを残して3分割するという目的には、partition()
とrpartition()
が最も素直で安全です。
最初の出現で分けたいならpartition()
、最後の出現で分けたいならrpartition()
と覚えると使い分けに迷いません。
区切りがない時の戻り値や空文字の禁止、前後の空白処理、ケースインセンシティブの手順といったコツを押さえれば、設定解析、ログ整形、ファイル名処理、URLやパスの抽出など幅広い文字列処理で堅牢なコードを書けます。
最後に、「区切りを保持したいかどうか」を判断軸にsplit()
との違いを意識して選択してください。