今回はPythonのチュートリアル「The Python Tutorial」の内容を試しながら文字列の扱いについて覚えていこう。文字列は扱うことが多いデータなので、基本的な使い方は調べなくても済むように覚えてしまいたいところだ。
シングルクォーテーション、ダブルクォーテーション、バックスラッシュ
まず、次の実行結果を見てみよう。
>>> 'spam eggs' # single quotes
'spam eggs'
>>> 'doesn\'t' # use \' to escape the single quote...
"doesn't"
>>> "doesn't" # ...or use double quotes instead
"doesn't"
>>> '"Yes," they said.'
'"Yes," they said.'
>>> "\"Yes,\" they said."
'"Yes," they said.'
>>> '"Isn\'t," they said.'
'"Isn\'t," they said.'
>>>
Pythonでは文字列はシングルクォーテーションで囲ったもの、または、ダブルクォーテーションで囲ったものであることがわかる。ダブルクォーテーションで囲った場合には中にシングルクォーテーションを文字として含めることができ、シングルクォーテーションで囲った場合にはダブルクォーテーションを文字として含められることもわかる。
シングルクォーテーションで囲ったものにシングルクォーテーションを含める場合や、ダブルクォーテーションで囲ったものにダブルクォーテーションを含める場合には、文字の前にバックスラッシュを指定する。つまり\’または\”といった書き方をする。このあたりの規則は、Pythonに限らず多くのプログラミングに共通している。
次の実行例では文字列に\nを含めた場合の挙動を確認することができる。
>>> '"Isn\'t," they said.'
'"Isn\'t," they said.'
>>> print('"Isn\'t," they said.')
"Isn't," they said.
>>> s = 'First line.\nSecond line.' # \n means newline
>>> s # without print(), \n is included in the output
'First line.\nSecond line.'
>>> print(s) # with print(), \n produces a new line
First line.
Second line.
>>>
\nは通常改行を意味する指定だ。Pythonの場合、文字列に\nを含めて変数に代入すると、print()などを通じて出力した場合には\nが改行コードとして処理され、変数を直接指定した場合には文字列としてそのまま出力されていることがわかる。
なお、上記操作はタブを出力する\tでも同様だ。
また、print()で出力させるものの、\nを改行として処理せずに文字列として処理させたい場合には、次のようにクォーテーションの前に「r」を記述する。
>>> print('C:\some\name') # here \n means newline!
C:\some
ame
>>> print(r'C:\some\name') # note the r before the quote
C:\some\name
>>>
「r」は「raw(加工せずそのまま)」という単語の頭文字だと考えておくとわかりやすい。
トリプルクォート
Pythonで特徴的な文字列の書き方にトリプルクォートがある。これは”“”で囲うことで複数行の文字列を指定することができるというものだ。次のように使うことができる。
>>> print("""\
... Usage: thingy [OPTIONS]
... -h Display this usage message
... -H hostname Hostname to connect to
... """)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
>>>
””“の中では改行はそのまま改行として解釈されるので、複数行の文字列を記述する場合に見たとおりの出力が得られやすくて便利だ。なお、行末に\を書いておくと改行をキャンセルすることができる。上記チュートリアルだとトリプルクォートの最初が”“”\となっているから、文字列の一番最初に改行コードが入ることを防いでいることがわかる。
文字列の結合
Pythonは文字列の結合にも、ほかのプログラミング言語と比べるとユニークな部分がある。文字列の結合を次のように+演算子で指定することができるのだが、*で繰り返し結合が指定できるという特徴を備えている。
>>> # 3 times 'un', followed by 'ium'
...
>>> 3 * 'un' + 'ium'
'unununium'
>>>
「3 * ‘un’」は「un」を3回繰り返し結合という意味なので、「ununun」になっている。これに「+ ‘ium’」で「unununium」となるわけだ。チュートリアルではシングルクォートが使われているが、ここは別にダブルクォーテーションでも構わない。
クォーテーションでくくった文字列の場合には、次のように結合演算子を指定せずに並べるだけでも文字列結合を行うことができる。
>>> 'Py' 'thon'
'Python'
>>>
クォーテーションでくくった文字列を並べる方法は、次のように1行を超える文字列を書く場合などにも利用することができる。
>>> text = ('Put several strings within parentheses '
... 'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
>>>
ただし、並べることで文字列結合ができるのはクォーテーションで囲まれた文字列に対してのみで、次のように変数に代入された文字列と演算しようとしたり、演算結果を結合演算子なしで結合しようとしたりするとエラーになる。
>>> prefix = 'Py'
>>> prefix 'thon' # can't concatenate a variable and a string literal
File "<stdin>", line 1
prefix 'thon' # can't concatenate a variable and a string literal
^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^
SyntaxError: invalid syntax
>>>
次のように結合演算子「+」を挟めば、変数とクォーテーションで囲まれた文字列も結合することができる。
>>> prefix + 'thon'
'Python'
>>>
文字列とインデックス
Pythonの文字列はインデックスを指定して1文字だけ指し示したり、範囲を指定して一部の文字列を指し示すといった使い方ができる。ほかのプログラミング言語的には文字型の配列のような書き方に見える。
次のサンプルからわかるように、インデックスは0から始まっている。最初の文字が0で、次が1、その次が2といった具合だ。マイナス値を指定した場合には文字列の最後からのカウントになり、-1なら最後の文字、-2なら最後の文字の1つ手前の文字、となる。
>>> word = 'Python'
>>> word[0] # character in position 0
'P'
>>> word[5] # character in position 5
'n'
>>> word[-1] # last character
'n'
>>> word[-2] # second-last character
'o'
>>> word[-6]
'P'
>>> word[0:2] # characters from position 0 (included) to 2 (excluded)
'Py'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
>>> word[:2] # character from the beginning to position 2 (excluded)
'Py'
>>> word[4:] # characters from position 4 (included) to the end
'on'
>>> word[-2:] # characters from the second-last (included) to the end
'on'
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
>>>
Pythonの文字列は「スライス」という機能にも対応しており、[開始インデックス:終了インデックス]の形で利用する。「substring」という言葉のほうがピンとする方もいるかもしれない。スライスを考えるときは、1文字目の前が0、1文字目と2文字目の間が1、2文字目と3文字目の間が2と考えると、指定する数字と切り出される文字列との関係が理解しやすくなる。また、スライスでは開始を指定しなければ1文字目から、終了を指定しなければ最後の文字まで、といった解釈になる。
C言語のようなプログラミング言語に親しんでいると、日本語を指定した場合にどういった扱いになるのかが気になるところだが、Python 3系はもともとUnicodeに対応したプログラミング言語なので、バイト数などを気にすることなく日本語としての1文字をそのまま1文字として扱うことができる。3バイトとか4バイトとかエンコーディングを意識した処理を行う必要はない。日本語の文字列で同じ処理を行った場合は次のようになる。
>>> word='零壱弐参肆伍'
>>> word[0] # character in position 0
'零'
>>> word[5] # character in position 5
'伍'
>>> word[-1] # last character
'伍'
>>> word[-2] # second-last character
'肆'
>>> word[-6]
'零'
>>> word[0:2] # characters from position 0 (included) to 2 (excluded)
'零壱'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'弐参肆'
>>> word[:2] + word[2:]
'零壱弐参肆伍'
>>> word[:4] + word[4:]
'零壱弐参肆伍'
>>> word[:2] # character from the beginning to position 2 (excluded)
'零壱'
>>> word[4:] # characters from position 4 (included) to the end
'肆伍'
>>> word[-2:] # characters from the second-last (included) to the end
'肆伍'
>>> len(word)
6
>>>
インデックスを指定することで特定の文字を抜き出して使うことができるが、範囲外を指定するとエラーになる。ただし、インデックスの指定ではなくスライスの指定の場合には範囲外の指定でもエラーにならない。
>>> word = 'Python'
>>> word[42] # the word only has 6 characters
File "<stdin>", line 1
word[42] # the word only has 6 characters
^
IndentationError: unexpected indent
>>> word[4:42]
'on'
>>> word[42:]
''
>>> word[0] = 'J'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> 'J' + word[1:]
'Jython'
>>> word[:2] + 'py'
'Pypy'
>>>
インデックス、またはスライスで使用できるというのは、あくまでもアクセスできるだけであって、書き込むことはできない。インデックスを指定した対象に文字や文字列を代入しようとするとエラーになる。書き換えて使いたい場合には、新しく文字列を生成して使う必要がある。
文字列は基本中の基本
トリプルクォートやインデックス、スライスの指定はPythonに特有の文字列操作だが(最近では似たような機能を持ったプログラミング言語はいくつもあるのだが)、その他の操作はほかのプログラミング言語やスクリプト系の言語とそれほど違いはない。この辺りの記述の仕方はどのプログラミング言語でもある程度似てくるものだ。
文字列の操作は基本中の基本なので、この辺りはチュートリアルや言語仕様を見なくても読める&書けるようになっておきたいところだ。