Python での文字列の操作

PythonBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、Python の基本的なデータ型である文字列(string)を実際に操作する経験を積みます。まず、文字列の作成、イミュータビリティ(不変性)、そして正のインデックスと負のインデックスの両方を使用した個々の文字へのアクセス方法といった、文字列の基礎を理解することから始めます。

この基礎の上に、スライスを使用した部分文字列の抽出方法、操作や特殊な書式設定のための様々な文字列演算子とエスケープ文字の活用方法、そして文字列をフォーマットするためのさまざまなメソッドについて学びます。最後に、文字列の検索、置換、内容の変更といった操作を行うための一般的な文字列メソッドについて深く掘り下げます。

文字列の基礎とインデックス指定の理解

このステップでは、Python における文字列の基本的な概念、特に文字列の作成方法とインデックスを使用した個々の文字へのアクセス方法について学びます。文字列は文字のシーケンスであり、最も一般的なデータ型の一つです。文字列は、シングルクォート ('...') またはダブルクォート ("...") を使用して作成できます。

Python の文字列の重要な特徴は、それらがイミュータブル(不変)であることです。これは、一度作成されると内容を変更できないことを意味します。文字列を変更しているように見える操作は、実際には新しい文字列を作成しています。

これを検証してみましょう。WebIDE で、左側のファイルエクスプローラーから ~/project ディレクトリ内のファイル string_basics.py を開きます。以下のコードをそのファイルに追加してください。

## string_basics.py

## 文字列はイミュータブルです。変数に新しい文字列を代入すると、
## 新しいメモリアドレスを持つ新しい文字列オブジェクトが作成されます。
a = "hello"
print(f"Value: {a}, ID: {id(a)}")

a = "hi"
print(f"Value: {a}, ID: {id(a)}")

スクリプトを実行するには、WebIDE でターミナルを開き(Terminal -> New Terminal)、次のコマンドを実行します。

python ~/project/string_basics.py

ID の値が異なる、以下のような出力が表示され、新しい文字列オブジェクトが作成されたことが確認できます。

Value: hello, ID: <placeholder>
Value: hi, ID: <placeholder>

次に、文字列のインデックス指定について探ります。インデックス(位置)を使用して個々の文字にアクセスできます。Python では、最初の文字のインデックスは 0 から始まります。

string_basics.py ファイルを修正し、正のインデックス指定を含めます。

## string_basics.py
a = "Hello"

## 正のインデックス指定(先頭から)
print("Positive Indexing:")
print(a[0])
print(a[1])
print(a[2])
print(a[3])
print(a[4])

## 存在しないインデックスにアクセスすると IndexError が発生します。
## print(a[5])

ファイルを保存し、再度実行します。

python ~/project/string_basics.py
Positive Indexing:
H
e
l
l
o

Python は負のインデックス指定もサポートしており、これは文字列の末尾から文字にアクセスします。最後の文字はインデックス -1、最後から 2 番目の文字は -2 となります。

string_basics.py に負のインデックス指定の例を追加します。

## string_basics.py
a = "Hello"

## 正のインデックス指定(先頭から)
print("Positive Indexing:")
print(a[0])
print(a[1])
print(a[2])
print(a[3])
print(a[4])

## 負のインデックス指定(末尾から)
print("\nNegative Indexing:")
print(a[-5])
print(a[-4])
print(a[-3])
print(a[-2])
print(a[-1])

## 文字列はイミュータブルであるため、文字を変更することはできません。
## 次の行は TypeError: 'str' object does not support item assignment を引き起こします
## a[0] = "J"

ファイルを保存し、このステップの最後としてもう一度実行します。

python ~/project/string_basics.py
Positive Indexing:
H
e
l
l
o

Negative Indexing:
H
e
l
l
o

文字列のスライス

このステップでは、スライスを使用して文字列から部分文字列を抽出する方法を学びます。インデックス指定が単一の文字を取得するのに対し、スライスは一連の文字を取得します。

スライスの基本的な構文は string[start:end] です。これは、start インデックスから始まり、end インデックスの手前までの文字列の部分を抽出します。

~/project ディレクトリからファイル string_slicing.py を開きます。基本的なスライスのデモを行うために、以下のコードを追加してください。

## string_slicing.py
a = "Hello World"

## インデックス 0 からインデックス 5 の手前までをスライス
print(a[0:5])

## インデックス 6 から文字列の最後までをスライス
print(a[6:])

## 先頭からインデックス 5 の手前までをスライス
print(a[:5])

## スライスに負のインデックスを使用
print(a[-5:-2])

## 文字列全体のコピーを取得
print(a[:])

ファイルを保存し、ターミナルから実行します。

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World

スライスには 3 番目の引数 step を指定でき、構文は string[start:end:step] となります。step の値は、スライス内の文字間の間隔を決定します。

string_slicing.py を修正し、step を含む例を追加します。

## string_slicing.py
a = "Hello World"

## ... (前のコード) ...

b = "0123456789"

## 先頭から末尾まで、2 文字おきに文字を取得
print(b[::2])

## インデックス 1 から 7 の手前までを、ステップ 3 で取得
print(b[1:7:3])

## 負のステップは方向を反転させます。これは文字列全体を反転させます。
print(b[::-1])

## インデックス 7 からインデックス 2 の手前までを逆順に取得
print(b[7:2:-1])

ファイルを保存し、再度実行します。

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World
02468
14
9876543210
76543

スライスは柔軟性があり、範囲外のインデックスを自動的に処理するため、エラーを防ぎます。

この動作を確認するために、string_slicing.py にこれらの最終行を追加します。

## string_slicing.py
a = "Hello World"

## ... (前のコード) ...

b = "0123456789"

## ... (前のコード) ...

## 範囲外のインデックスでのスライス
c = "Python"
## エンドインデックスが文字列の長さを超えていますが、問題なく動作します。
print(c[2:100])

## スタートインデックスが先頭より前ですが、問題なく動作します。
print(c[-100:4])

スクリプトを保存して実行します。

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World
02468
14
9876543210
76543
thon
Pyth

文字列演算子とエスケープ文字の使用

このステップでは、文字列に使用される一般的な演算子と、特殊文字を表すためにエスケープ文字を使用する方法について学びます。

Python は、文字列操作のためにいくつかの演算子を提供しています。in および not in 演算子は部分文字列の存在を確認し、+ は文字列を連結し、* は文字列を繰り返します。

WebIDE でファイル string_operators.py を開き、以下のコードを追加してください。

## string_operators.py

## 'in' 演算子は、部分文字列が文字列内に存在するかどうかを確認します
print('e' in 'Hello')
print('x' in 'Hello')

## 'not in' 演算子は 'in' の逆です
print('e' not in 'Hello')
print('x' not in 'Hello')

## 連結 (+) は 2 つの文字列を結合します
print('Hello' + ' ' + 'World')

## 繰り返し (*) は文字列を指定された回数繰り返します
print('=' * 20)
print('Go! ' * 3)

ファイルを保存して実行します。

python ~/project/string_operators.py
True
False
False
True
Hello World
====================
Go! Go! Go!

次に、エスケープ文字について見ていきましょう。これらはバックスラッシュ (\) で始まる特殊なシーケンスで、印刷不可能な文字や特殊文字を表します。

ファイル escape_characters.py を開き、以下のコードを追加します。

## escape_characters.py

## \' または \" を使用して、文字列内に引用符を含めます
print('It\'s a beautiful day.')
print("He said, \"Python is fun!\"")

## \n は改行を作成します
print("First line\nSecond line")

## \t は水平タブを作成します
print("Column1\tColumn2\tColumn3")

## \\ はリテラルのバックスラッシュを表します
print("This is a backslash: \\")

## 'r' をプレフィックスとして付けた raw string (生文字列) は、バックスラッシュをリテラル文字として扱います。
## これはファイルパスや正規表現に非常に便利です。
print("A normal string: C:\\Users\\new_folder")
print(r"A raw string: C:\Users\new_folder")

ファイルを保存して実行します。

python ~/project/escape_characters.py
It's a beautiful day.
He said, "Python is fun!"
First line
Second line
Column1 Column2 Column3
This is a backslash: \
A normal string: C:\Users\new_folder
A raw string: C:\Users\new_folder

文字列のフォーマット

このステップでは、Python で文字列をフォーマットするためのモダンで効果的な方法について学びます。これは、変数や式を文字列内に埋め込むことで、動的で読みやすい出力を生成するために不可欠です。

+ 演算子を使用して文字列を連結することもできますが、数値などの文字列以外の型と混在させる場合、str() を使用して手動で変換する必要があるため、煩雑になります。

Python はより良い解決策を提供します。最も一般的で推奨される方法は、f-string(フォーマット済み文字列リテラル)を使用することです。

f-string によるフォーマット

Python 3.6 で導入された f-string は、式を文字列内に埋め込むための簡潔で読みやすい方法を提供します。文字列の前に f または F を付け、波括弧 {} 内に式を記述するだけです。

ファイル string_formatting.py を開き、以下のコードを追加します。

## string_formatting.py

name = "Alice"
age = 30

## f-string を使用して変数を埋め込む
greeting = f"Hello, my name is {name} and I am {age} years old."
print(greeting)

## 式を直接埋め込むこともできます
print(f"In 5 years, I will be {age + 5} years old.")

スクリプトを保存して実行します。

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.

フォーマット指定子

f-string では、波括弧内のコロン (:) の後に続くフォーマット指定子を使用して、埋め込まれた値のフォーマットを制御することもできます。

string_formatting.py に以下の例を追加します。

## string_formatting.py

## ... (前のコード) ...

pi = 3.14159265

## 浮動小数点数を小数点以下 2 桁にフォーマット
print(f"The value of pi is approximately {pi:.2f}")

## 数値を先頭にゼロを付けて幅 8 にパディング
order_id = 45
print(f"Order ID: {order_id:08}")

## 指定されたスペース内でのテキストの配置 (幅 10)
## < (左寄せ), ^ (中央寄せ), > (右寄せ)
text = "Python"
print(f"'{text:<10}'")
print(f"'{text:^10}'")
print(f"'{text:>10}'")

## 桁区切り文字としてカンマを追加
large_number = 1234567890
print(f"A large number: {large_number:,}")

ファイルを保存し、再度スクリプトを実行します。

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.
The value of pi is approximately 3.14
Order ID: 00000045
'Python    '
'  Python  '
'    Python'
A large number: 1,234,567,890

str.format() メソッド

f-string が登場する前は、str.format() メソッドが文字列をフォーマットするための推奨される方法でした。これは、文字列内にプレースホルダーの波括弧 {} を配置し、その後 format() メソッドに値を渡すことで機能します。

string_formatting.py の末尾にこの例を追加します。

## string_formatting.py

## ... (前のコード) ...

## str.format() メソッドの使用
item = "moon"
cost = 99.95
statement = "The {} costs {:.2f} dollars.".format(item, cost)
print(statement)

ファイルを保存して実行し、出力を確認します。

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.
The value of pi is approximately 3.14
Order ID: 00000045
'Python    '
'  Python  '
'    Python'
A large number: 1,234,567,890
The moon costs 99.95 dollars.

str.format() は依然として有用ですが、一般的に f-string の方が可読性が高く、高速です。

一般的な文字列メソッドの探索

この最終ステップでは、文字列オブジェクトに対して最も一般的で便利な組み込みメソッドのいくつかを探ります。これらのメソッドは、大文字・小文字の変更、テキストの検索と置換、文字列のリストへの分割など、さまざまな操作を実行します。

文字列はイミュータブル(不変)であることを覚えておいてください。したがって、これらのメソッドは常に新しい文字列を返し、元の文字列を変更することはありません。

ファイル string_methods.py を開き、以下のコードを追加して、これらのメソッドがどのように機能するかを確認します。

## string_methods.py

## 大文字・小文字変換メソッド
s1 = "Hello, World!"
print(f"Original: '{s1}'")
print(f"Upper case: '{s1.upper()}'")
print(f"Lower case: '{s1.lower()}'")
print(f"Title case: '{s1.title()}'")
print("-" * 20)

## 検索と置換
s2 = "The quick brown fox jumps over the lazy dog."
print(f"Original: '{s2}'")
## 文字列が特定の部分文字列で始まるか終わるかを確認
print(f"Starts with 'The': {s2.startswith('The')}")
print(f"Ends with 'dog.': {s2.endswith('dog.')}")
## 部分文字列のインデックスを検索 (見つからない場合は -1)
print(f"Index of 'fox': {s2.find('fox')}")
## 部分文字列を別の文字列に置換
s3 = s2.replace("brown", "red")
print(f"After replace: '{s3}'")
print("-" * 20)

## 空白の除去 (Stripping whitespace)
s4 = "    some whitespace    "
print(f"Original: '{s4}'")
## strip() は両端から、lstrip() は左から、rstrip() は右から除去します
print(f"Stripped: '{s4.strip()}'")
print("-" * 20)

## 分割と結合 (Splitting and joining)
s5 = "one,two,three,four"
print(f"Original: '{s5}'")
## デリミタに基づいて文字列を部分文字列のリストに分割
parts = s5.split(',')
print(f"Split list: {parts}")
## リストの要素を区切り文字で単一の文字列に結合
s6 = " ".join(parts)
print(f"Joined string: '{s6}'")

ファイルを保存し、ターミナルから実行します。

python ~/project/string_methods.py

出力は次のようになります。

Original: 'Hello, World!'
Upper case: 'HELLO, WORLD!'
Lower case: 'hello, world!'
Title case: 'Hello, World!'
--------------------
Original: 'The quick brown fox jumps over the lazy dog.'
Starts with 'The': True
Ends with 'dog.': True
Index of 'fox': 16
After replace: 'The quick red fox jumps over the lazy dog.'
--------------------
Original: '    some whitespace    '
Stripped: 'some whitespace'
--------------------
Original: 'one,two,three,four'
Split list: ['one', 'two', 'three', 'four']
Joined string: 'one two three four'

これらは Python で利用可能な多くの文字列メソッドのほんの一部です。これらは、テキストデータを処理および操作するための強力なツールを提供します。

まとめ

この実験(Lab)では、Python で文字列を扱うための基本的な概念を学びました。まず、文字列の作成方法を理解し、そのイミュータブル(不変)な性質を認識することから始めました。次に、正のインデックスと負のインデックスの両方を使用して個々の文字にアクセスしたり、開始、終了、ステップパラメータを使用してスライスにより部分文字列を抽出したりする練習をしました。

その後、連結 (+) および繰り返し (*) のための文字列演算子を探り、特殊文字を文字列に含めるためにエスケープ文字を使用する方法を学びました。f-string の強力さと可読性、およびそのフォーマット指定子に焦点を当てた最新の文字列フォーマット技術を習得し、同時に str.format() メソッドも見ました。最後に、upper()lower()replace()strip()split()join() などの一般的な文字列メソッドを使用して、不可欠なテキスト操作タスクを実行する練習をしました。