閉じる

Pythonのスライスで文字列の一部を取得する方法まとめ

Pythonの文字列スライスは、短い記述で一部分を取り出したり、逆順にしたり、間引きしたりできる強力な機能です。

本記事では初学者にもわかる順序で、[start:stop:step]の基本から負のインデックス、エラーになりやすいポイント、Unicodeの注意点までを丁寧に解説します。

実行結果つきのサンプルで挙動を確かめながら学べます。

Pythonのスライスの基本(文字列)

書式[start:stop:step]の意味

スライスの基本書式はs[start:stop:step]です

ここで、startは開始位置、stopは終端(ただし後述の通り終端は含まれません)、stepは何文字ごとに進むかを表します。

各引数は省略できます。

Python
# 基本のサンプル: 英小文字で観察しやすく
s = "abcdefg"

print(s[1:5:2])   # 1から5未満まで2刻み → b, d
print(s[0:3])     # 0から3未満 → a, b, c
print(s[:4])      # start省略(先頭から)
print(s[3:])      # stop省略(末尾まで)
print(s[::])      # 全体をそのまま(コピー)
実行結果
bd
abc
abcd
defg
abcdefg

終端は含まない(半開区間)

Pythonのスライスは半開区間([start, stop))です。

つまり、stopの位置の文字は結果に含まれません。

この性質のおかげで、s[0:n]s[n:m]を自然に連結できます。

Python
s = "abcdefg"
print(s[1:4])   # 1,2,3の要素を取得
print(s[4])     # 4番目の要素(スライスの終端)は含まれていなかったことを確認
実行結果
bcd
e

省略時のデフォルト値

省略した引数にはデフォルト値が入ります

stepが正の場合と負の場合で、startstopのデフォルトが異なる点に注意します。

以下にまとめます。

省略対象step > 0 のときstep < 0 のとき
start0(先頭)-1(末尾から)
stoplen(s)(末尾の次)-(len(s)+1)(先頭の前)
step1-1
Python
s = "abcdef"
print(s[:])     # start/stop/stepすべて省略 → 全体コピー
print(s[::-1])  # stepだけ-1 → 逆順
print(s[:3])    # start省略 → 先頭から3未満
print(s[3:])    # stop省略 → 3以降すべて
実行結果
abcdef
fedcba
abc
def

インデックスは0始まり

Pythonのインデックスは0から始まります

最初の文字はs[0]です。

負のインデックスは末尾から数えますが、まずは0始まりになれると理解が安定します。

Python
s = "Python"
print(s[0], s[1], s[2])  # 0始まりで順に取り出し
実行結果
P y t

文字列スライスのよくある取得パターン

先頭n文字を取得する [:n]

先頭からn文字を取りたいときはs[:n]が最も簡潔です。

範囲外のnを指定してもエラーにならず、存在する分だけ取得されます。

Python
s = "こんにちはPython"
n = 5
print(s[:n])         # 先頭5文字
print(s[:100])       # 文字数を超えてもOK(自動クリップ)
実行結果
こんにちは
こんにちはPython

末尾n文字を取得する [-n:]

末尾からn文字s[-n:]です。

ログの末尾やファイル拡張子などの抽出に役立ちます。

Python
s = "report_2025_09.csv"
print(s[-4:])   # 拡張子 ".csv"
print(s[-7:])   # "9.csv"
実行結果
.csv
9.csv

任意範囲の部分文字列 [i:j]

i以上j未満の範囲を抜き出します。

インデックスの境界が外れても安全に動作します。

Python
s = "abcdefghij"
print(s[2:7])     # cdefg
print(s[-8:-3])   # d e f g h から -3(=h手前)まで → defg
実行結果
cdefg
defg

逆順にする [::-1]

逆順はs[::-1]が定番です。

回文判定のような用途でよく使います。

Python
s = "racecar"
print(s[::-1])           # 逆順
print(s == s[::-1])      # 回文か判定
実行結果
racecar
True

間引き抽出(step) [::2]

2文字おきに取りたい場合はs[::2]のようにstepを指定します。

奇数番目や偶数番目の抽出に便利です。

Python
s = "0123456789"
print(s[::2])   # 偶数インデックス(0,2,4,6,8)
print(s[1::2])  # 奇数インデックス(1,3,5,7,9)
実行結果
02468
13579

全体のコピー [:]

浅いコピーが欲しいときはs[:]です。

文字列はイミュータブルなので、コピーの要件がある処理で意図を明示したいときに使います。

Python
s = "immutable"
t = s[:]        # 全体コピー
print(t, s, t is s)  # 文字列は内部で同一化されることがある(実装依存)
実行結果
immutable immutable True

負のインデックスとstepの使い方

末尾から数える負のインデックス

負のインデックスは末尾から数えます

s[-1]は最後の文字、s[-2]は最後から2番目です。

Python
s = "abcdef"
print(s[-1])      # f (最後)
print(s[-3:])     # def (最後から3文字)
print(s[:-3])     # abc (最後の3文字を除く)
実行結果
f
def
abc

負のstepで逆方向に走査する

stepに負の値を指定すると、右から左に進みます。

startは右側、stopは左側を指すように設計するのがコツです。

Python
s = "abcdefghij"
print(s[8:2:-1])   # i(8) → 3まで逆向きに(2は含まない) → ihgfed
print(s[::-2])     # 2刻みで逆方向 → jihfdb
実行結果
ihgfed
jihfdb

範囲外でも空文字になる挙動

スライスは範囲外でも安全で、結果が存在しなければ""(空文字)になります。

例外は発生しません。

Python
s = "abc"
print(s[100:200])   # 範囲外 → 空文字
print(s[2:2])       # 開始と終了が同じ → 空文字
print(s[1:5:-1])    # 負のstepだが開始<終了 → 空文字
実行結果
(出力はありません)

スライスの注意点とTips

文字列はイミュータブル(スライス代入不可)

文字列はイミュータブルです。

s[0] = "X"のような代入はできません。

置換したいときはs = "X" + s[1:]のように新しい文字列を作成します。

Python
s = "hello"
try:
    s[0] = "H"            # 代入は不可
except TypeError as e:
    print(type(e).__name__, str(e))

# 置換したい場合は新しい文字列を作る
t = "H" + s[1:]
print(t)
実行結果
TypeError 'str' object does not support item assignment
Hello

ステップ0はエラー(ValueError)

stepに0は指定できません

必ず正または負の整数にします。

Python
s = "abc"
try:
    print(s[::0])     # 無効なstep
except ValueError as e:
    print(type(e).__name__, str(e))
実行結果
ValueError slice step cannot be zero

負のstep時の開始と終了の関係

負のstepではstartstopより右側にある必要があります。

そうでないと空文字になります。

Python
s = "abcdefgh"
print(s[5:1:-1])   # f e d c → fedc
print(s[1:5:-1])   # start(1)がstop(5)より左 → 空文字
実行結果
fedc

境界は自動クリップされる

スライスは自動的に境界をクリップします。

大きすぎるインデックスや小さすぎるインデックスを指定してもエラーにならず、存在する範囲で切り出します。

Python
s = "abcdef"
print(s[-100:1000])  # 全体
print(s[1000:])      # 空文字
print(s[:-1000])     # 空文字
実行結果
abcdef

sliceオブジェクト(slice)で可読性向上

sliceオブジェクト(slice(start, stop, step))を使うと、スライス範囲に名前を付けたり再利用でき、可読性が高まります。

辞書や関数引数で渡したいときにも便利です。

Python
# sliceを事前に定義して再利用
front3 = slice(0, 3)       # 先頭3文字
even_idx = slice(0, None, 2)

names = ["Python", "Slicing", "Beginner"]
for w in names:
    print(w[front3], w[even_idx])

# dictや関数に渡して使うケース
def take(s: str, sl: slice) -> str:
    return s[sl]

mid = slice(2, 6)
print(take("ABCDEFGHIJ", mid))
実行結果
Pto Pto
SliSlc
Beg Bgne
CDEF

Unicodeの結合文字に注意

スライスはコードポイント単位で行われるため、見た目の1文字(グラフェム)を途中で分断してしまうことがあります。

特に結合文字や国旗・家族絵文字に注意が必要です。

コード例(落とし穴のデモ)

Python
import unicodedata

# "é" は単一コードポイントのNFCと、"e"+"◌́"のNFDで見た目が同じになる
nfc = "é"                  # U+00E9
nfd = "e\u0301"            # U+0065 + U+0301

print(nfc, len(nfc))       # 見た目1文字、長さ1
print(nfd, len(nfd))       # 見た目1文字、長さ2

# NFDの先頭1文字だけを取ると、結合記号が切り落とされる
print(nfd[:1])             # "e" (アクセントが消える)

# 国旗絵文字は2コードポイントの組み合わせ
flag = "🇯🇵"               # Regional Indicator Symbols 2つの連結
print(flag, len(flag))
print(flag[:1])            # 半分に割れてしまい不自然
実行結果
é 1
é 2
e
🇯🇵 2
🇯

対処のヒント

  • 正規化: unicodedata.normalize("NFC", s)で可能なら単一コードポイントへまとめ、分断リスクを減らします。
  • グラフェム単位の分割: サードパーティのregexモジュール(標準のreではありません)の\Xで見た目の1文字単位に分割できます。環境が許せば次のように扱います。
Python
# pip install regex が必要(環境に応じて導入)
import regex as re

s = "abcdef"
n = 3
graphemes = re.findall(r"\X", s)
print(graphemes[:n])  # 見た目の文字単位で安全にスライス
実行結果
['a', 'b', 'c']

まとめ

本記事では、文字列スライス[start:stop:step]の基本から、半開区間という重要概念、省略時のデフォルト負のインデックスや負のstepの実践的な使い方までを段階的に解説しました。

文字列はイミュータブルであり、stepが0はエラー境界は自動クリップされるなど、例外を避ける設計になっている一方、Unicodeの結合文字は思わぬ落とし穴になります。

必要に応じて正規化やグラフェム単位処理を使い分けると安心です。

基礎を押さえれば、部分取得、逆順、間引きなどの典型操作を短いコードで安全かつ明快に記述できます。

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

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

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

URLをコピーしました!