Pythonで文字列処理をやっていたところ、またはまりました。個人的な備忘録として記録しております。今、stringという変数に 'abcde(fg)h.' という文字列を入れておきます。この文字列の ) の直後に空白を挿入するプログラムを以下のように書きました。
--------------------------
string = 'abcde(fg)h.'
j = string.find(')')
string2 = string[:j] + ' ' + string[j+1:]
pring (string2)
--------------------------
ところが結果は以下のようになってしまいます。
'abcde(fg h.'
) の後ろに空白が入らず、)が空白で上書きされてしまいます。
j には 配列 string におけるindex番号 8 が入るはずです。
そこで、string2には、string の0~8である、'abcde(fg)' に空白 ' ' を加え、さらに stringの9~10の 'h.' を付け加え、 'abcde(fg) h.' という文字列を入れるつもりでした。それで、
string2 = string[:j] + ' ' + string[j+1:] と書きました。
ところが実際には ) が空白で上書きされます。
結局正解は、下記のように書くことでした。
string2 = string[:j] + ' ' + string[j:]
確かにこれだと、直前に挿入するか、直後に挿入するかで、どこを、+1 にするか -1 にするかで悩まなくてよいので、便利といえば便利ですが、ちょっと気持ち悪いです。
結局、分かったのは、配列のインデックスで string[x : y]と書いたとき、実際に取得されるのは string[x] から string[y-1] の範囲となるようで(つまり指定した値の一つ手前までしか読み取らない、つまり、x : y は x 以上 y 未満の意味)、 [x] から [y] の範囲ではないということです。ですので、その次の部分を取得するのに、[y+1:z] としてしまうと、[y] が抜けてしまうということでした。
結局、インデックスが1から始まるのではなく、0から始まるので、このような仕様にしておくと、例えば文字列の長さなどを取得したときに、長さの値をindexに使っても、indexの範囲を超える心配がない、ということのようです。具体的に言うと仮に string という文字列を入れた変数の長さが10だとすると、len (string) の値は10になります。しかし stringの末尾のindex値は、string[9]になり、取得した長さより、1少なくなります。仮に、参照するのは、直前の値まで、というルールでないとすると、string[0:len(string)]としたときに、最後に、string[10]を読みに行こうとするので、indexの範囲を超えエラーになってしまう筈です。しかし、実際には、9までしか読まないので、参照する末尾の値は string[9] で止まり、エラーになりません。
これが、FORTRANやBASICのように、配列のindexが1から始まるのが原則になっている言語だと末尾のindexの値は、変数の長さと一致するので、こういう問題は起こりません。従って読み取る範囲も、指定する値通りで良い、という話になります。
私は、配列のインデックスが 原則1 から始まる言語に慣れていましたので、引っ掛かってしまったのでした。新しくコンピュータ言語を勉強される方は、こんなところで引っかからないでしょう。自分の備忘録として記しておきます。