テキスト処理の基本

PythonPythonBeginner
今すぐ練習

This tutorial is from open-source community. Access the source code

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

このセクションでは、テキストを扱う方法について説明します。

リテラルテキストの表現

文字列リテラルは、プログラム内で引用符を使って書かれます。

## シングルクォート
a = 'Yeah but no but yeah but...'

## ダブルクォート
b = "computer says no"

## トリプルクォート
c = '''
Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,
not around the eyes,
don't look around the eyes,
look into my eyes, you're under.
'''

通常、文字列は1行に収まります。トリプルクォートは、複数行にまたがる括られたすべてのテキスト(すべての書式設定も含む)をキャプチャします。

シングルクォート (') とダブルクォート (") を使う違いはありません。 ただし、文字列の始まりに使った同じ種類の引用符を、終わりにも使う必要があります

文字列エスケープコード

エスケープコードは、制御文字やキーボードで直接入力しにくい文字を表すために使用されます。以下は一般的なエスケープコードです:

'\n'      改行
'\r'      復帰
'\t'      タブ
'\''      リテラルのシングルクォート
'\"'      リテラルのダブルクォート
'\\'      リテラルのバックスラッシュ

文字列の表現

文字列の各文字は、内部的には整数であるいわゆるUnicode「コードポイント」として格納されます。次のエスケープシーケンスを使用して、正確なコードポイント値を指定することができます:

a = '\xf1'          ## a = 'ñ'
b = '\u2200'        ## b = '∀'
c = '\U0001D122'    ## c = '𝄢'
d = '\N{FOR ALL}'   ## d = '∀'

Unicodeキャラクターデータベースは、利用可能なすべての文字コードのリファレンスです。

文字列のインデックス付け

文字列は、個々の文字にアクセスするための配列のように機能します。0から始まる整数インデックスを使用します。負のインデックスは、文字列の末尾からの相対位置を指定します。

a = 'Hello world'
b = a[0]          ## 'H'
c = a[4]          ## 'o'
d = a[-1]         ## 'd' (文字列の末尾)

また、:を使ってインデックスの範囲を指定することで、部分文字列(サブストリング)をスライスまたは選択することもできます。

d = a[:5]     ## 'Hello'
e = a[6:]     ## 'world'
f = a[3:8]    ## 'lo wo'
g = a[-5:]    ## 'world'

終了インデックスの文字は含まれません。欠落したインデックスは、文字列の先頭または末尾を想定します。

文字列操作

連結、長さ、所属判定、複製

## 連結 (+)
a = 'Hello' + 'World'   ## 'HelloWorld'
b = 'Say'+ a          ## 'Say HelloWorld'

## 長さ (len)
s = 'Hello'
len(s)                  ## 5

## 所属判定 (`in`, `not in`)
t = 'e' in s            ## True
f = 'x' in s            ## False
g = 'hi' not in s       ## True

## 複製 (s * n)
rep = s * 5             ## 'HelloHelloHelloHelloHello'

文字列メソッド

文字列には、文字列データに対して様々な操作を行うメソッドがあります。

例:先頭と末尾の空白を取り除く。

s =' Hello '
t = s.strip()     ## 'Hello'

例:ケース変換。

s = 'Hello'
l = s.lower()     ## 'hello'
u = s.upper()     ## 'HELLO'

例:テキストの置換。

s = 'Hello world'
t = s.replace('Hello ','Hallo')   ## 'Hallo world'

その他の文字列メソッド

文字列には、テキストデータをテストおよび操作するためのさまざまな他のメソッドがあります。これはメソッドの小さなサンプルです:

s.endswith(suffix)     ## 文字列がsuffixで終わるかどうかをチェックする
s.find(t)              ## sの中でtが最初に出現する位置
s.index(t)             ## sの中でtが最初に出現する位置
s.isalpha()            ## 文字がアルファベットかどうかをチェックする
s.isdigit()            ## 文字が数字かどうかをチェックする
s.islower()            ## 文字が小文字かどうかをチェックする
s.isupper()            ## 文字が大文字かどうかをチェックする
s.join(slist)          ## sを区切り文字として文字列のリストを結合する
s.lower()              ## 小文字に変換する
s.replace(old,new)     ## テキストを置換する
s.rfind(t)             ## 文字列の末尾からtを検索する
s.rindex(t)            ## 文字列の末尾からtを検索する
s.split([delim])       ## 文字列を部分文字列のリストに分割する
s.startswith(prefix)   ## 文字列がprefixで始まるかどうかをチェックする
s.strip()              ## 先頭と末尾の空白を取り除く
s.upper()              ## 大文字に変換する

文字列の不変性

文字列は「不変」または読み取り専用です。作成されると、値を変更することはできません。

>>> s = 'Hello World'
>>> s[1] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError:'str' object does not support item assignment
>>>

文字列データを操作するすべての操作とメソッドは、常に新しい文字列を作成します。

文字列変換

任意の値を文字列に変換するには、str() を使用します。結果は、print() 文によって生成されるのと同じテキストを保持する文字列です。

>>> x = 42
>>> str(x)
'42'
>>>

バイト文字列

8ビットのバイトの文字列は、低レベルの入出力で一般的に遭遇するもので、以下のように書かれます。

data = b'Hello World\r\n'

最初の引用符の前に小文字のbを付けることで、通常のテキスト文字列とは対照的に、それがバイト文字列であることを指定します。

ほとんどの通常の文字列操作が機能します。

len(data)                         ## 13
data[0:5]                         ## b'Hello'
data.replace(b'Hello', b'Cruel')  ## b'Cruel World\r\n'

インデックス付けは少し異なります。なぜなら、それは整数としてバイト値を返すからです。

data[0]   ## 72 ('H'のASCIIコード)

テキスト文字列への変換とその逆変換。

text = data.decode('utf-8') ## バイト -> テキスト
data = text.encode('utf-8') ## テキスト -> バイト

'utf-8' 引数は文字エンコーディングを指定します。他の一般的な値には 'ascii''latin1' があります。

生文字列

生文字列は、解釈されないバックスラッシュ付きの文字列リテラルです。最初の引用符の前に小文字の「r」を付けることで指定されます。

>>> rs = r'c:\newdata\test' ## 生文字列 (解釈されないバックスラッシュ)
>>> rs
'c:\\newdata\\test'

文字列は、入力された通りのその中に囲まれたリテラルテキストです。これは、バックスラッシュが特別な意味を持つ状況で便利です。例:ファイル名、正規表現など。

f文字列

フォーマットされた式置換付きの文字列。

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> a = f'{name:>10s} {shares:10d} {price:10.2f}'
>>> a
'       IBM        100      91.10'
>>> b = f'Cost = ${shares*price:0.2f}'
>>> b
'Cost = $9110.00'
>>>

注:これにはPython 3.6以降が必要です。 フォーマットコードの意味については後で説明します。

これらのチャレンジでは、Pythonの文字列型に対する操作を試してみましょう。これは、結果を簡単に確認できるPythonの対話型プロンプトで行う必要があります。重要な注意事項:

インタプリタと対話するチャレンジでは、>>> はPythonが新しい文を入力するように求めるときに表示されるインタプリタのプロンプトです。チャレンジのいくつかの文は複数行にまたがっています。これらの文を実行するには、何度か「return」キーを押す必要がある場合があります。これらの例を実行するときに >>> を入力しないでください。

まずは、次のような株価シンボルのシリーズを含む文字列を定義しましょう。

>>> symbols = 'AAPL,IBM,MSFT,YHOO,SCO'
>>>

演習1.13:個々の文字と部分文字列の抽出

文字列は文字の配列です。いくつかの文字を抽出してみましょう。

>>> symbols[0]
?
>>> symbols[1]
?
>>> symbols[2]
?
>>> symbols[-1]        ## 最後の文字
?
>>> symbols[-2]        ## 負のインデックスは文字列の末尾から始まります
?
>>>

Pythonでは、文字列は読み取り専用です。

symbols の最初の文字を小文字の 'a' に変更してみることでこれを確認しましょう。

>>> symbols[0] = 'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>

演習1.14:文字列の連結

文字列データは読み取り専用ですが、常に新しく作成された文字列を変数に再代入することができます。

次の文を試してみてください。これは、新しいシンボル "GOOG" を symbols の末尾に連結します。

>>> symbols = symbols + 'GOOG'
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCOGOOG'
>>>

あっ!これは望んだ結果ではありません。修正して、symbols 変数に 'AAPL,IBM,MSFT,YHOO,SCO,GOOG' の値が入るようにしてください。

>>> symbols =?
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

文字列の先頭に 'HPQ' を追加します。

>>> symbols =?
>>> symbols
'HPQ,AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

これらの例では、元の文字列が修正されているように見えるかもしれませんが、文字列が読み取り専用であることに反しているように見えます。そうではありません。文字列の操作は、毎回まったく新しい文字列を作成します。変数名 symbols が再代入されると、新しく作成された文字列にポイントが移ります。その後、古い文字列はもはや使用されないので破棄されます。

演習1.15:メンバーシップテスト(部分文字列テスト)

部分文字列をチェックするために in 演算子を使って実験してみましょう。対話型プロンプトで、次の操作を試してください。

>>> 'IBM' in symbols
?
>>> 'AA' in symbols
True
>>> 'CAT' in symbols
?
>>>

なぜ 'AA' のチェックは True を返したのでしょうか?

演習1.16:文字列のメソッド

Pythonの対話型プロンプトで、いくつかの文字列のメソッドを試してみましょう。

>>> symbols.lower()
?
>>> symbols
?
>>>

文字列は常に読み取り専用であることを忘れないでください。操作の結果を保存したい場合は、それを変数に格納する必要があります。

>>> lowersyms = symbols.lower()
>>>

さらにいくつかの操作を試してみましょう。

>>> symbols.find('MSFT')
?
>>> symbols[13:17]
?
>>> symbols = symbols.replace('SCO','DOA')
>>> symbols
?
>>> name = '   IBM   \n'
>>> name = name.strip()    ## 周囲の空白を削除する
>>> name
?
>>>

演習1.17:f文字列

時には、文字列を作成してその中に変数の値を埋め込みたい場合があります。

そのためには、f文字列(f-string)を使います。たとえば:

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> f'{shares} shares of {name} at ${price:0.2f}'
'100 shares of IBM at $91.10'
>>>

演習1.10の mortgage.py プログラムを変更して、f文字列(f-string)を使ってその出力を作成してください。出力がきれいに整列するようにしてみてください。

✨ 解答を確認して練習

演習1.18:正規表現

基本的な文字列操作の1つの制限は、高度なパターンマッチングをサポートしていないことです。そのためには、Pythonの re モジュールと正規表現を使う必要があります。正規表現の処理は大きなトピックですが、以下に短い例を示します。

>>> text = 'Today is 3/27/2018. Tomorrow is 3/28/2018.'
>>> ## 日付のすべての出現箇所を見つける
>>> import re
>>> re.findall(r'\d+/\d+/\d+', text)
['3/27/2018', '3/28/2018']
>>> ## 日付のすべての出現箇所を置換テキストに置き換える
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2018-3-27. Tomorrow is 2018-3-28.'
>>>

re モジュールに関する詳細情報については、公式ドキュメントを https://docs.python.org/library/re.html で確認してください。

解説

インタプリタを使って実験を始めるとき、異なるオブジェクトがサポートする操作についてもっと知りたいことがよくあります。たとえば、文字列で利用可能な操作をどのように調べるかということです。

あなたのPython環境によっては、タブ補完を通じて利用可能なメソッドの一覧を見ることができるかもしれません。たとえば、次のように入力してみてください。

>>> s = 'hello world'
>>> s.<tab key>
>>>

タブキーを押しても何も起こらない場合は、組み込みの dir() 関数に頼ることができます。たとえば:

>>> s = 'hello'
>>> dir(s)
['__add__', '__class__', '__contains__',..., 'find', 'format',
'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition',
'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit',
'rstrip','split','splitlines','startswith','strip','swapcase',
'title', 'translate', 'upper', 'zfill']
>>>

dir()(.) の後に現れるすべての操作のリストを生成します。特定の操作に関する詳細情報を取得するには help() コマンドを使います。

>>> help(s.upper)
Help on built-in function upper:

upper(...)
    S.upper() -> string

    Return a copy of the string S converted to uppercase.
>>>

まとめ

おめでとうございます!あなたは文字列の実験を完了しました。あなたのスキルを向上させるために、LabExでさらに多くの実験を行って練習してください。