この[番号](オフセット,インデックス)は文字列の先頭からのバイト数ではなく,1バイト文字(アスキーの英数字)と2バイト文字(漢字かなカナ)が混じっていても,先頭を0番とする番号で文字を取り出すことができる.
文字列を定義してから,後で文字列を書き換えることのできる言語もある(C言語やjavascriptでは書き換えられる,ミュータブル:mutable)が,Pythonでは文字列は書き換えられない(イミュータブル:immutable)オブジェクトとして定義されている.
そこで,いったん定義された文字列の中の1文字に,他の文字を「直接に代入しようとする」とエラーになる.
>>> s1 = 'abcdeFGHIJ'
>>> s1[5] = 'f'
→ エラー
後に述べる文字列操作関数を利用しても,文字列の書き換えを行うことができるが,次のように文字列そのものを「再定義する」(文字列のコピーを代入して,文字列全体を定義し直す)と,文字列の書き換えと同じ効果が得られる.
上記の文字列の5番目の文字を小文字のfに書き換えるには
>>> s1 = 'abcdeFGHIJ'
>>> s1 = s1[:5]+'f'+s1[6:]
>>> s1
→ 'abcdefGHIJ'
6. 文字列操作の組み込み関数
pythonで文字列操作に使える組み込み関数(ビルドイン関数,Pythonのシステムであらかじめ用意されていて,ユーザ各自が定義しなくてもそのまま使える関数)の幾つか
(1) len(str) … 文字列の長さを返す
この関数len()は,オブジェクトの長さ (要素の数) を返し,引数には文字列だけでなく,シーケンス (文字列,タプル,リスト,rangeなど)およびコレクション (辞書,集合,など)にも使える.
【書式】
len(要素数を調べたい文字列の名前)
【例 6.1】
>>> s1 = 'abcdeFGHIJ'
>>> len(s1)
→ 10
>>> len(s1[::3])
→ 4 (2つ置きに取った文字列 adGJ の長さは4)
(2) split('目印の文字') … 文字列を分割する
【書式】
文字列.split('目印の文字')
• 元の文字列中の'目印の文字'をセパレーターとして文字列を分割して,カンマ(,)区切りのリストが作られる.
• 新たにリストが作られ,split()を使っただけでは元の文字列は変化しない.
【例 6.2.1】
>>> str6 = 'Rome was not built in a day.'
>>> list1 = str6.split(' ')
→ ['Rome', 'was', 'not', 'built', 'in', 'a', 'day.']
[半角スペース(' ')を区切り文字として指定すると,半角文字を取り除いたカンマ(,)区切りのリストが作られる.]
【書式】
文字列.split()
• セパレータの'目印の文字'を省略すると,デフォルト(既定値)として半角スペース(' ')が区切り文字として用いられる.
ただし,半角スペース(' ')をセパレータに指定した場合には,厳格に1つの半角スペース(' ')で1つの区切りができるのに対して,セパレータを省略した場合には半角スペース(' ')が幾つかつながっている場合にも,まとめて1つの区切りとなる.
さらに,引数なしのデフォルト(既定値)で使うと,先頭の余分なスペース,全角スペース,印字されない空文字(タブ,改行など)も取り除いて1つの区切りになる.
【例 6.2.1】
>>> str6 = 'Rome was__not built___in a day.'
(書き手の気分次第で,wasの後にスペースが2個,buildの後にスペースが3個入っている場合)
>>> str6.split(' ')
→ ['Rome', 'was', '', 'not', 'built', '', '', 'in', 'a', 'day.']
(繰り返される半角スペース(' ')のうちの1つは区切り文字として取り除かれるが,残りは半角スペース(' ')という文字となる)
>>> str6.split()
→ ['Rome', 'was', 'not', 'built', 'in', 'a', 'day.']
(セパレータを省略すると,半角スペースが複数個つながっている場合も1つの区切りと見なされる)
>>> str6 = 'Rome was not built in a day.'
(wasの後に全角スペース(2バイト文字)を入れてしまった場合)
>>> str6.split(' ')
→ ['Rome', 'was\u3000not', 'built', 'in', 'a', 'day.']
(セパレータとして半角スペース(' ')を指定すると,全角スペースは区切りとはならず,UTF-8の漢字コード\u3000になる)
>>> str6.split()
→ ['Rome', 'was', 'not', 'built', 'in', 'a', 'day.']
(セパレータを省略すると,半角スペースも全角スペースも区切り文字と見なされる)
>>> str7 = ' Rome was\tnot built\nin a\t\nday.'
(先頭に全角スペースと半角スペースが隣り合っており,wasの後ろにタブコード,buildの後に改行コード,aの後にタブと改行が隣り合っている)
→ ['Rome', 'was', 'not', 'built', 'in', 'a', 'day.']
(セパレータを省略すると,全角,半角のスペース,タブ,改行が複数個つながっている場合も1つの区切りと見なされる)
【書式】
文字列.split(sep=None, maxsplit=−1)
• split()関数の第1引数はセパレータとする目印の文字で,第2引数として最大分割回数を整数値で指定できます.
• 最大分割回数をn個にすると,植木算の仕組みでリストの要素数は最大でn+1個になります.
• 何らかの都合で最大分割回数を指定して,実際にはそれよりも多い区切り文字があるとき,後ろにある超過する部分はまとめて1つの要素に入ります.
• 最大分割回数が省略されたときは,制限なく分割されますが,その場合は引数として−1が使われています.
• 第2引数も指定するときに,第1引数を省略するとエラーになって,ここまでに述べたセパレータ省略の長所が利用できませんが,これを防ぐには第1引数としてNoneを指定するとよい.(NoneはTrueやFalseと同様に記号定数で,クォーテンションマークなしで直接書きます.先頭は大文字でなければなりません.)
【例 6.2.2】
>>> str1=' Rome was not build in a day. '
(Romeの前に余計なスペースがある.この文を5個まで分割したい.)
>>> str1.split(' ',4)
→ ['', 'Rome', 'was', 'not', 'build in a day. ']
>>> str1.split(None,4)
→ ['Rome', 'was', 'not', 'build', 'in a day. ']
(3) 'str'.join(list) … 文字列を結合する
split()の逆の操作です.
このメソッド(オブジェクトの中に定義されている関数)は,書き方がとても奇妙に見えます.
すなわち,先頭に書く(str)はオブジェクトの名前でなく,文字列を挟むために使う文字列です.listのところには,文字列を要素とするリスト型のデータを書きます.
【書式】
文字列.join(文字列から成るリスト)
• 元の文字列中の'目印の文字'をセパレーターとして文字列を分割して,カンマ(,)区切りのリストが作られる.
【例 6.3.1】
>>> str1='Rome was not build in a day.'
>>> list1 = str1.split()
>>> list1
→ ['Rome', 'was', 'not', 'built', 'in', 'a', 'day.']
>>> ' '.join(list1)
→ 'Rome was not built in a day.' (元のスペース区切りの文字列に戻せる)
>>> ''.join(list1)
→ 'Romewasnotbuiltinaday.' (空白を詰めた文字列ができる)
>>> ' - '.join(list1)
→ 'Rome - was - not - built - in - a - day.' (スペース,ハイフン,スペースの3文字( - )でつないだ文字列ができる)
>>> str2='\n'.join(list1)
>>> print(str2)
Rome
was
not
built
in
a
day.
(単語ごとに改行できる)
(4) 文字列.upper() … 小文字を大文字に変える
【書式】
文字列.upper()
• 元の文字列中に英字,ギリシャ文字,ローマ数字のように大文字と小文字の区別のある文字が含まれるとき,小文字を大文字に変えます.
(このメソッド(関数)と同様の関数は,他の様々な言語にもあります.英大文字は英小文字よりも文字コードが32[0x20]だけ小さいので,各文字コードを−32[−0x20]しているように見えますが,Pythonでは元の文字列に「大文字が含まれる場合」「大文字小文字の区別がない場合」「全角文字が含まれる場合」にも対応しています)
【例 6.4】
>>> str1='abc'
>>> str1.upper()
→ 'ABC' (英小文字は英大文字になります)
>>> str2='ABC'
>>> str2.upper()
→ 'ABC' (英大文字は変更されません)
>>> str3='0123., あいう'
>>> str3.upper()
→ '0123., あいう' (大文字,小文字の区別がない文字は変更されません)
>>> str4='abcABC'
>>> str4.upper()
→ 'ABCABC' (全角文字も小文字は大文字になり,大文字は変化しません)
>>> str5='αβγΓΔ'
>>> str5.upper()
→ 'ΑΒΓΓΔ' (ギリシャ文字も小文字は大文字になり,大文字は変化しません)
>>> str6='@ABTUV'
>>> str6.upper()
→ 'TUVTUV' (ローマ数字も小文字は大文字になり,大文字は変化しません)
※この他,á, ì, ëなどの発音記号にも丁寧に対応しているようです.
>>> str7='大小きゃしゅチェニョ'
>>> str7.upper()
→ '大小きゃしゅチェニョ' (これらは変わりません.ジョークでした.)
(5) 文字列.lower() … 大文字を小文字に変える
【書式】
文字列.lower()
• upper()の逆です
【例 6.5】
>>> str1 = '123.0abcABCあいうアイウabcABCωφθΩΦΘ@ABTUV'
>>> str1.lower()
→ '123.0abcabcあいうアイウabcabcωφθωφθ@AB@AB'
(大文字は小文字になり,全角大文字も全角小文字になり,すでに小文字である文字や大文字小文字の区別のない文字は変わりません.)
(6) 文字列1.count(文字列2) … 文字列1に含まれる文字列2の個数を数える
【書式】
文字列1.count(文字列2)
【例 6.6】
>>> str1 = 'A certain man had a donkey, which had carried the corn-sacks to the mill indefatigably for many a long year; but his strength was going, and he was growing more and more unfit for work. Then his master began to consider how he might best save his keep; but the donkey, seeing that no good wind was blowing, ran away and set out on the road to Bremen. "There," he thought, "I can surely be town-musician." When he had walked some distance, he found a hound lying on the road, gasping like one who had run till he was tired. "What are you gasping so for, you big fellow?" asked the donkey.' (グリム童話集「ブレーメンの音楽隊」の第1段落)
>>> str1.count('a')
→ 40 (この数え方では,man, hadのような単語の中のaも全部数える)
>>> str1.count(' a ')
→ 3 (不定冠詞のaを数えるには,この形.ただし、先頭のAは数えられていない)
>>> str1.count('the')
→ 6 (たまたま,Then, Thereなどが大文字で始まるためカウントされなかった)
>>> str1.count('e')
→ 49 (英語では,通常eが最も多くなる)
(7) 文字列1.replace(旧文字列, 新文字列, 回数) … 文字列1に含まれる旧文字列を新文字列に書き換える
【書式】
文字列1.replace(旧文字列, 新文字列, 回数)
• テキストエディタ,WordやExcelなどにある「置換」という機能と同じです.
• 第3引数の回数は省略でき,第3引数が省略された場合は,旧文字列に該当する部分文字列はすべて新文字列に書き換えられる.
• 第3引数の回数が正の整数nで与えられた場合,文字列1の左端からn個まで書き換えられる(旧文字列がn個よりも少なければ全部書き換えられる)
• replace()は元の文字列1を書き換えたコピーとしての文字列を返し,元の文字列は変化しない.
【例 6.7】
>>> str1 = 'おはよう。こんにちは。こんばんは。'
>>> str1.replace('。','.')
→ 'おはよう.こんにちは.こんばんは.' (。がすべて.に書き換えられる)
>>> str1.replace('。','.',2)
→ 'おはよう.こんにちは.こんばんは。' (初めから2個までの。が.に書き換えられる)
>>> str1.replace('。','.',4)
→ 'おはよう.こんにちは.こんばんは.' (2≦4だから全部書き換えられる)
>>> str2 = str1.replace('。','.')
>>> str1
→ 'おはよう。こんにちは。こんばんは。' (str1は変化しない)
>>> str2
→ 'おはよう.こんにちは.こんばんは.' (コピーで作られたstr2は書き換わっている)
(8) 文字列1.find(sub, start, end) … 文字列1の中で,オフセット(左端を0番とした文字の番号)がstart以上end未満の位置で最初に見つかる部分文字列subのオフセット
【書式】
文字列1.find(sub, start, end)
文字列1.index(sub, start, end)
• strat, endは省略できる.
• startを省略すれば既定値で文字列の先頭番号0から探す.endを省略すれば文字列の末尾の次len(文字列1)を指定したのと同じになる.startとendの両方を省略すれば,文字列の全体から探す.
• 部分文字列subが見つからなかったときは,−1が返される.
• 文字列1の中に部分文字列が「有るか無いか」だけならば,in演算子で調べられる.
• 文字列1.index(sub, start, end)によって,文字列1.find(sub, start, end)とほぼ結果が得られるが,部分文字列subが見つからなかったときエラーとなる点が異なる.
【例 6.8】
>>> str1 = 'A certain man had a donkey'
>>> str1.find('a')
→ 6 (A_certain 最初のaは6番目にある)
>>> str1.find('a', 7)
→ 11 (A certain man 7番目以降にある最初のaは11番目)
>>> str1.find('a',20,30)
→ −1 (20番目のdonkeyのdの後にaはない)
>>> 'a' in str1
→ True (有ればTrueが返される[場所は分からない])
>>> 'C' in str1
→ False (小文字のcはあるが大文字のCはないからFalseが返される)
>>> str1.index('a', 7)
→ 11
>>> str1.index('C')
→ エラー
(9) 文字列1.rfind(sub, start, end) … 文字列1の中で,オフセット(左端を0番とした文字の番号)がstart以上end未満の位置で「一番右」に見つかる部分文字列subのオフセット
【書式】
文字列1.rfind(sub, start, end)
文字列1.rindex(sub, start, end)
• 文字列1.find(sub, start, end), 文字列1.index(sub, start, end)と同様であるが文字列の右側から(後ろから)検索する
【例 6.9】
>>> str1 = 'A certain man had a donkey'
>>> str1.rfind('a')
→ 18 (A certain man had a donkey)
>>> str1.rindex('C')
→ エラー
(10)
文字列1.isdecimal(), 文字列1.isdigit(), 文字列1.isnumeric()
【書式】
文字列1.isdecimal()
文字列1.isdigit()
文字列1.isnumeric()
※ unicodeは日進月歩と言われていますが,2019年3月3日現在,実装されているPython 3のシステムでは,次のようになります.
• isdecimal() … decimal(10進数)であるか否かを調べる.次の表の背景色がピンク色の範囲にある文字に対してTrueを返し,それ以外にはFalseを返す.
• isdigit() … digit(数字)であるか否かを調べる.次の表の背景色が黄色の範囲にある文字に対してTrueを返し,それ以外にはFalseを返す.
• isnumeric() … numeric(数字に関するもの)であるか否かを調べる.次の表の背景色が水色の範囲にある文字に対してTrueを返し,それ以外にはFalseを返す.
• decimalに入るものは,digitにも入り,digitに入るものはnumericにも入る.
【decimal】
0,1,2,…, 9 半角アラビア数字(10進数)
0, 1, 2, …, 9 全角アラビア数字(10進数)
【digit】
@, A, …, H 9までの丸数字
⑴, ⑵, …, ⑼ アラビア数字の囲み文字(9まで)
⒈, ⒉, …, ⒐ 点付きの数字
【numeric】
T, U, … ,] ローマ数字(大)
@, A, … ,I ローマ数字(小)
〇, 一, 二, … , 十 漢数字
零, 壱, 弐, 参, 拾, 廿, 卅 漢数字の大字
百, 千, 万, 萬, 億, 兆 大きい方の補助単位
I, J, … 10以上の丸数字
⑽, ⑾, …, ⒆ 10以上の囲み数字
㈠ ㈡, …, ㈩ 漢数字の囲み文字
㊀ ㊁, …, ㊉ 漢数字の丸数字
⅐ ⅑, …, ⅚ 分数記号
【数ではない文字】
. 小数点
− マイナスの符号
半角スペース
空文字
京(
)以上の大きい方の補助単位
分, 厘, 毛, … 漠(10分の1以下の補助単位)
【例 6.10.1】
>>> str1 = '01234567890123456789'
>>> print(str1.isdecimal(),str1.isdigit(),str1.isnumeric())
→ True True True (str1は,すべてdecimalかつdigitかつnumeric)
【例 6.10.2】
>>> list1 = ['@','A','H','\u2474','\u2475','\u247c','\u2488','\u2490']
(16進数のunicodeをPythonに渡すには,先頭に\uを付ける)
>>> for kk in list1:
print(kk,kk.isdecimal(),kk.isdigit(),kk.isnumeric())
→
@ False True True
A False True True
H False True True
⑴ False True True
⑵ False True True
⑼ False True True
⒈ False True True
⒉ False True True
⒐ False True True
(list1の各要素は,すべてdecimalでなく,かつdigitであり,かつnumericである)
【例 6.10.3】
>>> list2=['T','@','〇','零','百','I','\u247d','\u3220','\u3280','\u2150']
>>> for kk in list2:
print(kk,kk.isdecimal(),kk.isdigit(),kk.isnumeric())
→
T False False True
@ False False True
〇 False False True
零 False False True
百 False False True
I False False True
⑽ False False True
㈠ False False True
㊀ False False True
⅐ False False True
(list2の各要素は,すべてdecimalでなく,かつdigitでなく,かつnumericである)
【例 6.10.4】
>>> list3=['.','-',' ','','京','分']
>>> for kk in list3:
print(kk,kk.isdecimal(),kk.isdigit(),kk.isnumeric())
→
. False False False
- False False False
False False False
False False False
京 False False False
分 False False False
(list3の各要素は,すべてdecimalでなく,かつdigitでなく,かつnumericでない)
(11) 文字列1.isascii(), 文字列1.isalpha(), 文字列1.isalnum()
文字列1の全部が0〜0x7Fまでのアスキー文字(1バイト文字)か,
文字列1の全部が半角または全角のアルファベット,漢字,かな,カナであるか,
文字列1の全部が漢字,かな,カナ,数字に関するものか
に応じて,True, Falseを返す
【書式】
文字列1.isascii()
文字列1.isalpha()
文字列1.isalnum()
• alphaはアルファベットよりもはるかに広い範囲になっていて,数字以外で読める文字は全部alphaと考えるとほぼ合う.
• alphaに入るものは,必ずalnumに入るので,alphaであってかつalnumでないもの(図の灰色の部分)はない.
• どれにも入らないのは,全角の演算記号など.
• 半角カタカナもalpha,alnumに入る.
【例 6.11.1】
>>> list4=['a','b','0','1','*','/','A','B','α','Ω','あ','ア','ア','鈴','田','0','1','U','B','I','*','/','#']
>>> for kk in list4:
print(kk,kk.isascii(),kk.isalpha(),kk.isalnum())
→
a True True True
b True True True
0 True False True
1 True False True
* True False False
/ True False False
A False True True
B False True True
α False True True
Ω False True True
あ False True True
ア False True True
ア False True True
鈴 False True True
田 False True True
0 False False True
1 False False True
U False False True
B False False True
I False False True
* False False False
/ False False False
# False False False
○== メニューに戻る ==