文字列の基本

最もよく扱うデータ型は数値ではなくテキストです。ユーザー名、メール、記事、JSON データ、HTML……すべて文字列です。このレッスンでは Python の文字列操作を体系的に学びます。


1. 3 種類の引用符

Python では 3 通りの方法で文字列を定義できます:

PYTHON
# シングルクォート
s1 = 'Hello'

# ダブルクォート
s2 = "Hello"

# トリプルクォート(複数行文字列)
s3 = """This is the first line
This is the second line
This is the third line"""

シングルクォートとダブルクォートは同等です——1 つを選んで一貫して使いましょう:

PYTHON
# この 2 つは同等
name = 'Xiao Ming'
name = "Xiao Ming"

ただし、文字列に引用符が含まれる場合は、使い分けが必要です:

PYTHON
# 文字列にシングルクォートが含まれる場合、ダブルクォートで囲む
text = "It's a beautiful day"
print(text)              # It's a beautiful day

# 文字列にダブルクォートが含まれる場合、シングルクォートで囲む
text = 'He said: "Hello!"'
print(text)              # He said: "Hello!"

# またはエスケープ文字を使う(推奨しない。可読性が低下)
text = 'It\'s a beautiful day'
💡 ヒント:****ダブルクォートを一貫して使うことをお勧めします。英語のテキストにはアポストロフィ(don't、it's)がよく含まれます。シングルクォートだとエスケープが必要になります。ダブルクォートならその手間がありません。

トリプルクォート:複数行テキストに最適

トリプルクォート(""" または ''')は改行や書式を保持します:

PYTHON
# トリプルクォートを使った複数行テキスト
message = """Dear Customer,

Thank you for choosing our service. Your order has been confirmed.
Estimated delivery: 3 business days.

If you have any questions, please contact support.
Have a nice day!"""

print(message)

出力:

TEXT
Dear Customer,

Thank you for choosing our service. Your order has been confirmed.
Estimated delivery: 3 business days.

If you have any questions, please contact support.
Have a nice day!

トリプルクォートは以下のような場面でよく使われます:長いテキスト、ドキュメンテーション文字列、関数の説明。


2. エスケープ文字

文字列の中に直接書けない文字(改行、タブ、引用符など)があります。そのような場合はエスケープ文字を使います——バックスラッシュ \ の後に文字を続けます。

エスケープ 意味
\n 改行
\t タブ
\\ バックスラッシュそのもの
\' シングルクォート
\" ダブルクォート
PYTHON
print("First line\nSecond line")           # \n 改行
print("Name:\tZhang San\tAge:\t25")        # \t タブ揃え
print("C:\\Users\\XiaoMing\\Desktop")      # \\ バックスラッシュを出力
print("He said: \"Hello!\"")               # \" ダブルクォート

出力:

TEXT
First line
Second line
Name:	Zhang San	Age:	25
C:\Users\XiaoMing\Desktop
He said: "Hello!"

例:エスケープ文字で表を整形(難易度 ⭐)

PYTHON
# \t を使って表を揃える
print("Item\tPrice\tQty\tTotal")
print("------------------------")
print("Apple\t5.0\t3\t15.0")
print("Banana\t3.5\t5\t17.5")
print("Milk\t12.0\t2\t24.0")
▶ 試してみよう

出力:

TEXT
Item	Price	Qty	Total
------------------------
Apple	5.0	3	15.0
Banana	3.5	5	17.5
Milk	12.0	2	24.0
💡 ヒント:\t はテキストの位置揃えに便利ですが、内容の長さが異なる場合は完全に揃わないことがあります。本番環境では f-string の書式設定({value:10} で 10 文字幅を確保)を使ってください。


3. Raw 文字列

Windows のファイルパスを書いたことがある人なら、この問題を経験したことがあるでしょう:

PYTHON
# しまった!\n が改行として解釈される
path = "C:\Users\new_folder\documents"
print(path)
# 出力:C:\Users
#        ew_folder\documents

解決策:文字列の前に r を付けると、Python に「エスケープ文字を処理せず、そのまま出力する」ように指示できます:

PYTHON
# ✅ Raw 文字列 — r プレフィックス
path = r"C:\Users\new_folder\documents"
print(path)
# 出力:C:\Users\new_folder\documents

raw 文字列では、各文字はそれ自身です——\n はもはや改行を意味せず、\t はタブを意味しません。

PYTHON
# 正規表現パターン(後で使います)
pattern = r"\d{3}-\d{8}"   # 電話番号のマッチ:010-12345678

# ファイルパス
log_path = r"D:\logs\app\2026\06\error.log"

print(f"Log path: {log_path}")
⚠️ 補足:raw 文字列の最後の文字はバックスラッシュにできません——r"abc\" はエラーになります。なぜでしょうか?\" はエスケープとして扱われませんが、パーサーはバックスラッシュが引用符をエスケープしていると見なし、文字列が終了していないことになります。


4. 文字列のインデックス

文字列は文字のシーケンスであり、各文字には位置(インデックス)があります。Python のインデックスは 0 から始まります:

PYTHON
text = "Python"
# インデックス:0→P  1→y  2→t  3→h  4→o  5→n

print(text[0])    # P
print(text[1])    # y
print(text[5])    # n

Python は負のインデックスもサポートしており、右から左に数えます。-1 は最後の文字です:

PYTHON
text = "Python"
print(text[-1])   # n(最後)
print(text[-2])   # o(最後から 2 番目)
print(text[-3])   # h
print(text[-6])   # P(最初)

インデックス図

TEXT
Positive:  0    1    2    3    4    5
       ┌────┬────┬────┬────┬────┬────┐
       │ P  │ y  │ t  │ h  │ o  │ n  │
       └────┴────┴────┴────┴────┴────┘
Negative: -6   -5   -4   -3   -2   -1

例:ID 番号から情報を抽出(難易度 ⭐)

PYTHON
# ID 番号から基本情報を抽出
id_number = "110101199001011234"

# 最初の 6 桁:地域コード
address_code = id_number[:6]      # スライスは後で説明
print(f"Region code: {address_code}")

# 7~14 桁:生年月日
birth = id_number[6:14]
year = birth[:4]
month = birth[4:6]
day = birth[6:8]
print(f"Date of birth: {year}-{month}-{day}")

# 最後の桁(-1):チェックサム
last_digit = id_number[-1]
print(f"Checksum: {last_digit}")
▶ 試してみよう

出力:

TEXT
Region code: 110101
Date of birth: 1990-01-01
Checksum: 4
💡 ヒント:string[6:14]スライスと呼ばれます。次に説明します。


5. 文字列のスライス

スライスは文字列から部分文字列を抽出します。構文:string[start:end:step]

PYTHON
text = "Hello, Python!"

# 基本スライス:start:end(end は含まない)
print(text[0:5])      # Hello(文字 0~4)
print(text[7:13])     # Python

ショートカット

PYTHON
text = "Hello, Python!"

print(text[:5])       # Hello — start を省略、先頭からインデックス 5 まで
print(text[7:])       # Python! — end を省略、インデックス 7 から最後まで
print(text[:])        # Hello, Python! — すべて

ステップ

PYTHON
text = "Hello, Python!"

print(text[::2])      # Hlo yhn! — 1 文字おき
print(text[1::2])     # el,Pto — インデックス 1 から始めて 1 文字おき

負のステップ(逆順)

PYTHON
text = "Hello, Python!"

print(text[::-1])     # !nohtyP ,olleH — 文字列全体を反転!
print(text[5:0:-1])   # ,olle — インデックス 5 から 0 へ、逆方向

スライスの例

PYTHON
# 実用的なスライステクニック
url = "https://www.example.com"

# プロトコルプレフィックスを除去
without_https = url[8:]    # www.example.com
print(without_https)

# ドメインを取得
domain = url[8:-4]         # www.example
print(domain)

# 文字列を反転
name = "racecar"
reversed_name = name[::-1]   # racecar(回文)
print(name == reversed_name)  # True — 回文です!

# 1 文字おき
code = "H1e2l3l4o5"
clean = code[::2]           # Hello
print(clean)

出力:

TEXT
www.example.com
www.example
True
Hello
💡 ヒント:[::-1] は Python で文字列を反転する古典的な方法です——シンプルでエレガントです。スライスは決して IndexError を起こさないことに注意してください——start や end が文字列の長さを超えても、Python は安全に取得できる範囲を返します。


6. よく使われる文字列メソッド

文字列には多くの組み込みメソッドがあります。ここでは最も一般的なものを紹介します。すべてを暗記する必要はありません——何が使えるかを知っておけば十分で、練習しながら覚えていきます。

大文字小文字の変換

PYTHON
text = "Hello, Python!"

print(text.upper())         # HELLO, PYTHON!
print(text.lower())         # hello, python!
print(text.title())         # Hello, Python!
print(text.capitalize())    # Hello, python!

空白の除去

PYTHON
text = "   Hello, World!   "

print(f"|{text}|")                # |   Hello, World!   |
print(f"|{text.strip()}|")        # |Hello, World!| — 両側
print(f"|{text.lstrip()}|")       # |Hello, World!   | — 左のみ
print(f"|{text.rstrip()}|")       # |   Hello, World!| — 右のみ

検索と置換

PYTHON
text = "Hello, Python! Python is fun!"

print(text.find("Python"))      # 7 — 最初の出現位置
print(text.find("Java"))        # -1 — 見つからない場合、-1 を返す
print(text.count("Python"))     # 2 — 出現回数

new_text = text.replace("Python", "Java")
print(new_text)                  # Hello, Java! Java is fun!

# replace は最大置換回数を指定できる
partial = text.replace("Python", "Java", 1)
print(partial)                   # Hello, Java! Python is fun!

チェックメソッド

PYTHON
print("hello".isalpha())        # True — すべて英字
print("hello123".isalpha())     # False — 数字を含む
print("12345".isdigit())        # True — すべて数字
print("hello123".isalnum())     # True — 英字と数字
print("hello!".isalnum())       # False — 感嘆符を含む
print("   ".isspace())          # True — すべて空白
💡 ヒント:これらのチェックメソッドは入力検証に非常に便利です。たとえば、ユーザー入力がすべて数字かどうかを確認する:if user_input.isdigit(): とすることで int() 変換が失敗しないことを保証できます。

分割と結合

PYTHON
# split():文字列 → リスト
sentence = "I love Python"
words = sentence.split()
print(words)                     # ['I', 'love', 'Python']

# 区切り文字を指定
csv_line = "Zhang San,25,Beijing"
fields = csv_line.split(",")
print(fields)                    # ['Zhang San', '25', 'Beijing']

# join():リスト → 文字列
parts = ["2026", "06", "23"]
date = "-".join(parts)
print(date)                      # 2026-06-23

例:データクリーニング(難易度 ⭐⭐)

PYTHON
# 汚れたユーザー入力をシミュレート
raw_data = "   Zhang San  ,  25  ,  Beijing  \n"

# クリーニング処理
# 1. strip() で先頭・末尾の空白を除去
cleaned = raw_data.strip()
print(f"Step 1: |{cleaned}|")

# 2. split() でカンマ区切り
fields = cleaned.split(",")
print(f"Step 2: {fields}")

# 3. 各フィールドの余分なスペースを除去
name = fields[0].strip()
age = fields[1].strip()
city = fields[2].strip()

print(f"Name: {name}")
print(f"Age: {age}")
print(f"City: {city}")
▶ 試してみよう

出力:

TEXT
Step 1: |Zhang San  ,  25  ,  Beijing|
Step 2: ['Zhang San  ', '  25  ', '  Beijing']
Name: Zhang San
Age: 25
City: Beijing

7. len():文字列の長さを取得

len() は Python の組み込み関数で、文字列(または他のシーケンス)の長さを返します:

PYTHON
text = "Hello, Python!"
print(len(text))              # 15

# 中国語の文字も 1 文字としてカウント
chinese = "你好世界"
print(len(chinese))           # 4

# 空文字列の長さは 0
print(len(""))                # 0

# よくある使い方:入力長の制限
username = "Xiao Ming"
if len(username) < 2:
    print("Username too short")
elif len(username) > 10:
    print("Username too long")
else:
    print(f"Username '{username}' is valid")
💡 ヒント:Python 3 では、文字列の長さは文字をカウントし、バイトではありません。len("中") は 1 を返し、3 ではありません(Python 2 では 3 を返します)。これにより文字列操作がより直感的になります。


よくあるユースケース


❓ よくある質問

Q シングルクォートとダブルクォート、どちらを使うべきですか?なぜ Python は両方を許可しているのですか?
A 歴史的に、Python の設計者はプログラマーに選択肢を与えることを信条としていました。C/Java のプログラマーはダブルクォートを好み、JavaScript のプログラマーは両方を使います。ダブルクォートを一貫して使うことをお勧めします。英語にはアポストロフィ(it's、don't、can't)がよくあるため、ダブルクォートならエスケープの必要がありません。何より重要なのは、プロジェクト内で一貫性を保つことです——両方を混在させないでください。
⚠️ Q:なぜ終了インデックスは除外されるのですか?たとえば text[0:5] はインデックス 5 を含まないのですか? A:これは Python の設計哲学——半開区間 [start, end) によるものです。2 つの利点があります:1)text[:5] は覚えやすい(最初の 5 文字)。2)text[0:5]text[5:10] は重複やギャップなくシームレスに接続します。慣れればこの設計の良さがわかります。

Q find()index() の違いは何ですか?
A 同じことを行います——部分文字列の位置を見つけます。違い:find() は見つからない場合に -1 を返し、index() はエラー(ValueError)を発生させます。日常的には安全な find() を使いましょう。部分文字列の存在が確実な場合(固定フォーマットのデータからの抽出など)は index() を使います。
Q なぜ文字列メソッドは元の文字列を変更しないのですか?(例:text.upper()text を変更しない)
A Python の文字列はイミュータブル(不変)だからです。一度作成されると変更できません。text.upper() は実際には新しい文字列を返し、元の text は変わりません。これによりデータの安全性が保証されます——関数に文字列を渡しても、密かに変更されることはありません。文字列を「変更」するには、スライスと連結で新しい文字列を作成します。

📖 まとめ

  • 文字列には 3 つの引用符の形式がある:シングル、ダブル、トリプル。ダブルクォートを推奨
  • エスケープ文字 \n\t\\ などで特殊文字を表現
  • Raw 文字列 r"..." はバックスラッシュのエスケープを防ぎ、パスや正規表現に最適
  • インデックスは 0 から始まり、負のインデックスをサポート(-1 は最後の文字)
  • スライス [start:end:step] で部分文字列を抽出。end は含まない。負の step で反転
  • よく使われるメソッド:strip()split()join()find()replace()
  • チェックメソッド:isdigit()isalpha()isalnum() など、入力検証に使用
  • 文字列はイミュータブル——すべての「変更」は新しい文字列を作成する

📝 練習問題

  1. 基本(難易度 ⭐)s = "Python programming is fun!" として、以下の操作を行ってください:

    • 最初の 6 文字を抽出
    • 最後の 4 文字を抽出
    • 文字列全体を反転
    • すべての文字を大文字に変換
  2. 中級(難易度 ⭐⭐):メールバリデーターを書いてください。email = "user@example.com" として、以下を確認:

    • @ を含むか
    • @ の両側に内容があるか(どちらも空ではない)
    • .com.cn.org のいずれかで終わるか
    • 各チェック結果を出力(True/False)ヒントfind()@ の位置を特定、スライスで両側を確認。
  3. 挑戦(難易度 ⭐⭐⭐):データクリーナーを書いてください。以下のデータが与えられています:

    TEXT
    data = "   Zhang San, 25 ,  Beijing  ;  Li Si  ,  30,  Shanghai  ;  Wang Wu  ,  22,  Guangzhou  "
    

    ; で分割して各人のデータを取得し、その後 , で分割して各フィールドを取得します。strip() で各フィールドをクリーニングし、きれいに揃えた表を出力します:

    TEXT
    Name       Age  City
    ────────────────────
    Zhang San  25   Beijing
    Li Si      30   Shanghai
    Wang Wu    22   Guangzhou
    
100%