フォームから届いた名前の前後に、なぜか空白が入っている。CSVから読んだ日付が、余計な改行つきで返ってくる。
プログラムを書いていると、こういう小さな汚れとの戦いが延々と続きます。あなたも一度は経験があるのではないでしょうか。
こうした整形作業のために、Pythonは文字列そのものに便利な機能をたくさん持たせています。それが文字列メソッドです。
ただ、種類が多いぶん、名前が似ていて紛らわしいものもあります。特にstripは、多くの学習者が同じ場所でつまずく代表格です。
この記事では、実務でよく使う文字列メソッドを、手元で動かせるコードと一緒に整理していきます。
文字列メソッドは、元の文字列を変えない¶
最初に、いちばん大事な性質を押さえておきましょう。Pythonの文字列は、あとから中身を書きかえられません。
そのため文字列メソッドは、元の文字列を加工するのではなく、加工済みの新しい文字列を返します。
name = " 山田太郎 "
name.strip() # 新しい文字列が返るだけ
print(repr(name)) # ' 山田太郎 ' ←元は変わっていない
name = name.strip() # 結果を受け取り直す
print(repr(name)) # '山田太郎'
s = "abc"
s[0] = "z" # TypeError: 'str' object does not support item assignment
2行目を実行しただけで満足してしまうミスは、初心者のうちに必ず一度は通る道です。メソッドの結果は変数に代入し直さないと、どこにも残りません。
リストのsortメソッドが元のリストを並べかえるのとは、正反対の動きです。この違いを頭に入れておくと、混乱がぐっと減ります。
まずは空白を落とすstripから¶
実務でいちばん出番が多いのは、前後の余白を取り除くstripでしょう。引数なしで呼ぶと、空白・タブ・改行をまとめて落としてくれます。
前だけ、後ろだけを対象にしたいときは、lstripとrstripを使い分けます。
raw = " \t 東京都 \n "
print(repr(raw.strip())) # '東京都'
print(repr(raw.lstrip())) # '東京都 \n '
print(repr(raw.rstrip())) # ' \t 東京都'
入力フォームやCSVから受け取った値は、まずstripに通す。そう習慣づけておくだけで、あとの比較処理で悩む回数が目に見えて減ります。
stripの引数は、文字の集合として扱われる¶
さて、ここからが本題です。stripには引数を渡せますが、この引数の解釈が直感とずれています。
渡した文字列は、そのままの並びとしてではなく、取り除きたい文字の集合として扱われます。次のコードを見てください。
print("sales.csv".rstrip(".csv")) # sale ←末尾のsまで消える
print("test_data".lstrip("test_")) # data ←偶然うまくいく例
print("total_data".lstrip("test_")) # otal_data ←tだけ消えてoで止まる
1行目で拡張子だけを落としたかったのに、salesの末尾のsまで消えてしまいました。ピリオド・c・s・vのどれかに当てはまる文字を、端から順に削り続けるためです。
3行目は逆に、消えてほしくないところで止まっています。集合に無いoに当たった時点で処理が終わるので、削れたのは先頭のtだけです。
私は10年ほどエンジニアとして開発に関わってきましたが、この挙動には過去に何度もやられました。ファイル名の一覧を作る処理で、末尾がsで終わる名前だけ1文字欠けるという、原因の見えにくいバグを出したこともあります。
Python公式のPEP 616でも、この混乱は正式に問題として認められています。そして解決策として、Python 3.9でremoveprefixとremovesuffixが追加されました。
print("sales.csv".removesuffix(".csv")) # sales
print("total_data".removeprefix("total_")) # data
こちらは指定した並びが丸ごと一致したときだけ、1回だけ取り除きます。一致しなければ、何も起きずに元の文字列が返ります。
前後の決まった文字列を落としたいなら、stripではなくこちらを選んでください。引数つきのstripは、文字の集合を削るための道具です。
分けるならsplit、つなぐならjoin¶
1本の文字列を複数に分けたいときはsplitを使います。区切り文字を渡すと、その位置で切り分けたリストが返ります。
引数を省略したときの動きが少し特殊なので、そこを先に確認しておきましょう。
print("192.168.0.1".split(".")) # ['192', '168', '0', '1']
print(" a b ".split()) # ['a', 'b'] ←空白の連続をまとめて処理
print("a,b,c".split(",", 1)) # ['a', 'b,c'] ←分ける回数を1回に制限
2行目のように引数なしで呼ぶと、連続した空白をひとかたまりとして扱い、空の要素も残しません。ログの1行をスペース区切りで分解したいときに便利です。
3行目のmaxsplitも覚えておくと重宝します。設定ファイルのキーと値のように、最初の区切りだけで分けたい場面で使えます。
分けたものをまた1本に戻すときは、joinの出番です。区切り文字のほうにメソッドが生えている点が独特なので、初見では戸惑うかもしれません。
【関連記事】Pythonのjoin()関数とは?文字列結合の基本から応用までjoin()関数の使い方を徹底解説
区切り文字を指定したときの空文字に注意¶
区切り文字を明示したsplitは、引数なしのときとは違って空の要素をそのまま残します。ここも事故が起きやすい場所です。
print("a,,b,".split(",")) # ['a', '', 'b', '']
CSVの行を素朴にsplitで分けると、値のない列がこうして空文字として現れます。そのままint関数へ渡せば、当然エラーで止まります。
実際のCSVはカンマを含む値やクォートの扱いもあるため、標準のcsvモジュールに任せるのが安全です。【関連記事】Pythonのcsvモジュールとは?表データの読み書きと文字化けの防ぎ方を初心者向けに解説
分けたあとに各要素をstripでそろえる書き方は、覚えておくと応用が利きます。
line = " 名前 : 山田 "
key, value = [part.strip() for part in line.split(":")]
print(repr(key), repr(value)) # '名前' '山田'
置きかえはreplace、回数も指定できる¶
文字列の一部を別のものに差しかえるにはreplaceを使います。第1引数が探すもの、第2引数が置きかえ後です。
見落とされがちですが、第3引数で置きかえる回数を制限できます。
print("a-b-c".replace("-", "_")) # a_b_c
print("a-b-c".replace("-", "_", 1)) # a_b-c ←最初の1回だけ
print("2026/08/22".replace("/", "-")) # 2026-08-22
該当する部分がなければ、エラーにはならず元の文字列がそのまま返ります。事前に存在チェックをする必要はありません。
なお、複雑な条件で探して置きかえたいなら、正規表現のほうが向いています。ただし読みにくくなりがちなので、単純な置換で足りるうちはreplaceを使ってください。
【関連記事】正規表現とは?複雑な文字列検索や置換を一瞬で終わらせる
探すときは in、位置がほしいときは find¶
ある文字列が含まれているかどうかを調べるだけなら、メソッドより先にin演算子を思い出してください。いちばん短くて読みやすい書き方です。
何文字目にあるかまで知りたいときに、findやindexを使います。
mail = "user@example.com"
print("@" in mail) # True
print(mail.find("@")) # 4
print(mail.find("!")) # -1 ←見つからないと-1
print(mail.partition("@")) # ('user', '@', 'example.com')
findは見つからないときに-1を返します。indexは同じ役割ですが、見つからないとValueErrorで止まる点が違います。
最後のpartitionは、最初の区切りの前・区切り自体・後ろの3つに分けて返します。区切りが無い場合も必ず3つ返るので、要素数の心配をしなくて済むのが利点です。
先頭や末尾のチェックには、startswithとendswithが使えます。タプルを渡せば、複数の候補をまとめて調べられます。
print("report.xlsx".endswith((".xlsx", ".xls"))) # True
数字かどうかの判定は、思ったより難しい¶
入力が数字だけかを確かめたい場面はよくあります。isdigitが便利そうに見えますが、ここには日本語環境ならではの罠があります。
全角の数字でもTrueになるのです。
print("123".isdigit()) # True
print("123".isdigit()) # True ←全角でもTrue
print("123".isdecimal()) # True
print("²".isdigit()) # True ←上付き文字までTrue
print("²".isdecimal()) # False
isdigitは上付き文字のような特殊な数字まで受けつけます。int関数に渡せる形かどうかを確かめたいなら、より条件の厳しいisdecimalのほうが安全です。
とはいえ、全角数字は素通りしてしまいます。数値として扱うつもりなら、判定に頼るよりint関数を実際に呼んで例外を捕まえるほうが確実です。
よく使う文字列メソッドを表で整理する¶
ここまで出てきたものと、実務で使う頻度の高いものをまとめておきます。迷ったときはここに戻ってきてください。
| メソッド | 何をするか | 例と結果 |
|---|---|---|
strip() |
前後の空白や改行を落とす | " a ".strip() → 'a' |
strip(chars) |
charsに含まれる文字を端から削る | "sales.csv".rstrip(".csv") → 'sale' |
removesuffix(s) |
末尾がsと一致すれば1回だけ外す | "sales.csv".removesuffix(".csv") → 'sales' |
split(sep) |
sepで分けてリストにする | "a,b".split(",") → ['a', 'b'] |
replace(a, b, n) |
aをbに置きかえる(n回まで) | "a-b-c".replace("-", "_", 1) → 'a_b-c' |
find(s) |
sの位置を返す(無ければ-1) | "abc".find("z") → -1 |
startswith(s) |
先頭がsかを調べる | "ab.py".startswith("ab") → True |
zfill(n) |
n桁になるまで先頭を0で埋める | "7".zfill(3) → '007' |
splitlines() |
改行で分ける(改行の種類を問わない) | "a\nb\r\nc".splitlines() → ['a', 'b', 'c'] |
zfillは伝票番号やファイル名の桁そろえで、splitlinesは複数行のテキストを1行ずつ処理するときに活躍します。
なお、文字列の一部を位置で切り出したいだけなら、メソッドを使わずスライスで済みます。【関連記事】Pythonのスライスとは?リストや文字列を切り出す書き方を初心者向けに解説
大文字と小文字の変換にも、ひとくせある¶
upperとlowerは名前のとおり、大文字と小文字をそろえるメソッドです。入力の表記ゆれを吸収したいときによく使います。
ただ、英語以外の文字が混じると事情が変わります。
print("Straße".lower()) # straße
print("Straße".casefold()) # strasse
print("it's a test".title()) # It'S A Test
比較のために表記をそろえるなら、lowerより徹底的に変換するcasefoldのほうが向いています。
titleは単語の先頭を大文字にしますが、アポストロフィの直後まで大文字にしてしまいます。人名の整形に使うと、思わぬ結果になるので気をつけてください。
実務で効いてくる、小さな習慣¶
最後に、私が現場で身につけた進め方を紹介します。特別なことは何もありません。
外から入ってきた文字列は、使う前に必ず整形する。 この一手間を挟むかどうかで、あとから追うバグの数がまるで変わります。
def normalize(value):
"""外部から受け取った文字列を比較できる形にそろえる。"""
return value.strip().casefold()
print(normalize(" Tokyo ") == normalize("TOKYO")) # True
整形の順番も大事です。先にstripしてから文字を消すと、消したあとに残った空白がそのまま居座ります。
print(repr(" 100 円 ".strip().replace("円", ""))) # '100 ' ←末尾に空白が残る
print(repr(" 100 円 ".replace("円", "").strip())) # '100'
削る処理を先に、stripを最後に。この順番を守るだけで、見えない空白に悩まされる回数が減ります。
また、組み立てた文字列を画面に出すときは、f-stringを使うと式をそのまま埋め込めて読みやすくなります。【関連記事】Pythonのf-stringとは?デバッグが驚くほど楽になる!
つまずきやすいポイントを整理しておく¶
覚えることは、そう多くありません。実際に手を動かすときに気をつける点だけに絞ってまとめます。
| つまずきポイント | 起きること | 対処 |
|---|---|---|
| メソッドを呼ぶだけで満足する | 元の文字列は変わらない | 結果を変数に代入し直す |
rstrip(".csv") で拡張子を消す |
直前の文字まで削れる | removesuffix() を使う |
split(",") の結果をそのまま使う |
空文字が混ざる | 各要素をstripし、空を除く |
isdigit() で数字判定 |
全角数字もTrueになる | isdecimal() かint関数と例外で判定 |
find() の結果をif文で見る |
0番目でもFalse扱いになる | in で存在確認する |
まずは手元のデータに .strip() を1つ足すところから始めてみてください。整形をひとつの関数にまとめておくと、あとで直す場所がひとつで済みます。
ここまでお読みいただきありがとうございました。