Python基礎講座 #7 文字列の扱い

読了 9分

Python基礎講座の7回目の講座、文字列の扱いを始めます。

文字列とは?

英語でstringと呼ばれる文字列は、キャラクター(character)の並びです。 文字列はシングルクォートやダブルクォートを使って表します。 ex) ‘string’ or “string” プラス(+)演算子を使って、文字列と文字列を結合できます。 ex) ‘schoolofweb’ + ‘.net" 実際にコードを実行しながら説明していきます。

>>> 'string'
'string'
>>> "string"
'string'

文字列の中にシングルクォートやダブルクォートを表示しなければならない場合があります。例のようなコードを実行すると構文エラーが発生してしまいます。

>>> 'I'm a programmer'
File "<stdin>", line 1
'I'm a programmer'
^
SyntaxError: invalid syntax

シングルクォートを表示したいときはダブルクォートで、ダブルクォートを表示したいときはシングルクォートで文字列を囲めば良いのです。

>>> "I'm a programmer"
"I'm a programmer"
>>> 'He says "Hello!"'
'He says "Hello!"'

もう一つの方法は、バックスラッシュを使って特殊文字を通常の文字としてエスケープ処理する方法もあります。上でエラーになったコードを修正して実行してみましょう。

>>> 'I\\'m a programmer'
"I'm a programmer"

今度はエラーなくちゃんと出力されるのが分かります。

文字列と文字列を結合したいときは、プラス演算子を使えば良いのです。

>>> 'schoolofweb' + '.' + 'net'
'schoolofweb.net'

しかし、文字列と数字を結合するには、数字を先に文字列に変換する必要があります。ageという変数の中の数字と文字列を結合してみます。

>>> 'I am ' + 18 + ' years old'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

型エラーが発生しているのが分かります。

今度は、文字列に変換してから結合してみましょう。

>>> 'I am ' + str(18) + ' years old'
'I am 18 years old'

問題なく結合されているのが分かります。

インデックシングとは?

インデックシングとは、ブラケット構文と数字を使って、文字列の中の特定の位置の文字を取り出すことを言います。Pythonは0から始まるゼロベースインデックスを使います。ゼロベースインデックスとは、インデックスの開始がゼロから始まるシステムです。つまり、最初のアイテムのインデックスが0になり、2番目のアイテムが1、3番目のアイテムが2になることを言います。

インデックスとリバースインデックス
インデックスとリバースインデックス
上の画像のようにSTRINGという文字列があるとき、最初の文字であるSが文字列の最初のアイテムになり、このアイテムのインデックスが0になります。右へ移動するほど、インデックスが1ずつ増えていきます。

最後のアイテムからインデックシングをすることをリバースインデックシングと言い、このとき、インデックスは-1から始まり1ずつ減っていきます。

STRINGという文字列を変数に保存した後、インデックスを使って最初の文字であるSを出力してみましょう。

>>> var = 'STRING'
>>> var[0]
'S'

今度はリバースインデックスを使って、最後の文字である「G」を出力してみましょう。

>>> var[-1]
'G'

この文字列のインデックスのレンジは0から5までです。しかし、このレンジを超えたインデックスを使うと、インデックスエラーが発生します。

先ほどPythonはゼロベースインデックスを使うと説明しましたが、実はC++、Java、JavaScriptなどほとんどの主流のプログラミング言語がゼロベースインデックスを使っています。しかし、Lua、Julia、Rのような言語はインデックスが1から始まるワンベースインデックスを使っています。

今度はスライシングを学んでいきましょう。

スライシングとは?

スライシングはインデックスと同じくブラケット構文を使って、文字列の中から文字や文字列を取り出す技術です。インデックシングでは一つの文字しか取り出せませんが、スライシングを使うと複数の文字を取り出せます。

スライシングの構文は、ブラケットの中に3つの数字を持ちます。数字と数字の間はコロンで区切ります。

スライシング構文

[start:stop:step]

startは取り出したい文字列の最初のキャラクターのインデックスです。 stopは取り出したい文字列の最後のキャラクターのインデックスに1を足した値です。 stepはstartからstopまでの増加幅を意味します。 stepは省略可能で、省略時はデフォルト値の1が使われます。 もし例の文字列から最初の3つのキャラクターを取り出したい場合は、[:3]を入力すれば良いのです。

>>> var[0:3]
'STR'

このとき、startインデックスが0であれば省略できます。

>>> var[:3]
'STR'

最後の3つのキャラクターを取り出したいなら、[-3:]を入力すれば良いです。

>>> var[-3:]
'ING'

真ん中の2つのキャラクターを取り出したいなら、[2:4]を使うか[-4:-2]を使えば良いです。

>>> var[2:4]
'RI'
>>> var[-4:-2]
'RI'

今度は数字とアルファベットが混ざった文字列に、step値を適用してアルファベットだけを取り出してみましょう。

>>> mixed = '1a2b3c'
>>> mixed[1::2]
'abc'

今度は、文字列の組み込みクラスが提供するメソッドについて見ていきましょう。

strのメソッド

upper:文字列を大文字に変換 lower:文字列を小文字に変換 capitalize:最初のキャラクターを大文字に変換 split:文字列をリストアイテムに分離 join:特定のキャラクターや文字列で他の文字を連結 strip:White spaceを削除 replace:特定のキャラクターを別のキャラクターに置換 format:文字列の中のplace holderに望む値を置き換え Pythonの中のすべてのものは、あるクラスのオブジェクトであり、クラスの中で定義されたメソッドを使えます。文字列クラスも様々な便利なメソッドを提供しています。

このうち、一般的によく使われるメソッドを使ってみましょう。

まず一つの文章を変数に保存し、type関数を使って変数に保存されたオブジェクトの型を確認してみましょう。

>>> greeting = 'welcome to schoolofweb.net.'
>>> type(greeting)
<class 'str'>

stringオブジェクトが保存されたことを確認しました。

dir関数を使って、stringオブジェクトがどんなメソッドを使えるかを出力してみましょう。

>>> dir(greeting)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

IPythonやjupyter notebookを使っている場合は、タブキーを使ってコードヒントを見ることもできます。

文字列クラスのメソッド
文字列クラスのメソッド
使用可能なメソッドがすべて見えるのが分かります。

最初のキャラクターを大文字に変換するcapitalizeメソッドを実行してみましょう。

>>> greeting.capitalize()
'Welcome to schoolofweb.net.'

今度は、すべての文字列を大文字に変換するupperメソッドと、すべての文字列を小文字に変換するlowerメソッドを実行してみましょう。

>>> greeting.upper()
'WELCOME TO SCHOOLOFWEB.NET.'
>>> greeting.lower()
'welcome to schoolofweb.net.'

今度は、特定の文字を使って文字と文字を連結するjoinメソッドを使ってみましょう。

>>> period = '.'
>>> abc = 'ABC'
>>> period.join(abc)
'A.B.C'

ABC文字列の各キャラクターがピリオドで連結されているのが分かります。

今度は、両サイドのwhite spaceを削除するstripメソッドを使ってみましょう。

>>> spaces = ' strip example '
>>> spaces.strip()
'strip example'

両サイドのwhite spaceが削除されているのが分かります。

次の文字列をカンマを基準にスプリットしてみましょう。

>>> numbers = 'one,two,three,four,five'
>>> numbers.split(',')
['one', 'two', 'three', 'four', 'five']

カンマを基準に各単語がリストアイテムに分離されているのが分かります。

今度は、特定のキャラクターや文字列を置換するreplaceメソッドを使ってみましょう。

>>> foo = 'this is a java tutorial for java programmers'
>>> foo.replace('java', 'python')
'this is a python tutorial for python programmers'

javaという文字列がpythonに置換されているのが分かります。

String Formatting

空のカーリーブレースを使う

'My name is {}. I am {} years old.'.format(name, age)

キーワードを使う

'My name is {name}. I am {age} years old.'.format(name=name, age=age)

インデックスを使う

'My name is {1}. I am {0} years old.'.format(age, name)

最後に確認するメソッドはformatメソッドです。formatメソッドを使うと、文字列の中にカーリーブレースで複数のプレースホルダーを定義した後、望む値で動的に置換できます。つまり、テンプレートを作って使うと考えてください。 formatメソッドを使うには、文字列の中にカーリーブレースを使ってプレースホルダーを定義します。このプレースホルダーの使い方は3つあります。最初の方法は、空のカーリーブレースを使う方法です。空のカーリーブレースを使うと、formatメソッドに渡される引数がプレースホルダーに順番に置換されます。

>>> name = 'Pink'
>>> age = 13
>>> 'My dog\\'s name is {}. She is {} years old.'.format(name, age)
"My dog's name is Pink. She is 13 years old."

プレースホルダーの数とメソッドに渡される引数の数は必ず同じでなければならず、もし数がマッチしないとインデックスエラーが発生します。この例のようにプレースホルダーは2つなのに引数を一つだけパスすると、インデックスエラーが発生します。

>>> 'My dog\\'s name is {}. She is {} years old.'.format(name)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: Replacement index 1 out of range for positional args tuple

2つ目の方法は、キーワードを使う方法です。プレースホルダーが多く、同じ値を何度も使う場合は、キーワードを使うことを推奨します。

>>> 'My dog\\'s name is {name}. She is {age} years old.'.format(name=name, age=age)
"My dog's name is Pink. She is 13 years old."

3つ目の方法は、インデックスを使う方法です。カーリーブレースの中にformatメソッドに渡される引数のインデックスを入力すれば良いのです。

>>> 'My dog\\'s name is {1}. She is {0} years old.'.format(age, name)
"My dog's name is Pink. She is 13 years old."

次のように数字の前にゼロパディングを表示することもできます。

>>> for i in range(1, 11):
...     print('file_{:03d}'.format(i))
...
file_001
file_002
file_003
file_004
file_005
file_006
file_007
file_008
file_009
file_010

ここでゼロは空欄をゼロのキャラクターで埋めるという意味で、3は文字列の最小の長さを意味します。

formatメソッドを使って小数点の桁数を定義することもできます。小数点を3桁だけ出力してみましょう。

>>> '{:.3f}'.format(1.55555)
'1.556'

末尾の小数点を切り捨てると四捨五入や切り捨てになることを覚えておいてください。

ログなどを出力するときに、文字の長さを揃えたり、左寄せ、中央、右寄せなどをして、見やすくフォーマッティングすることもできます。

>>> text = ''
>>> text += '{:10s} {:9s} {:4s}\\n'.format('First Name', 'Last Name', 'Age')
>>> text += '{} {} {}\\n'.format('-'*10, '-'*9, '-'*4)
>>> for person in people:
...     text += '{:>10s} {:^9s} {:<4d}\\n'.format(person['firstname'], person['lastname'], person['age'])
...
>>> print(text.strip())
First Name Last Name Age
---------- --------- ----
      John    Doe    30
      Jane    Doe    29
    Curtis    Lee    43

今回の講座はここで終わり、次の講座ではリストについて見ていきましょう。

X