省型旧形国電の残影を求めて

戦前型旧形国電および鉄道と変褪色フィルム写真を中心とした写真補正編集の話題を扱います。他のサイトでは得られない、筆者独自開発の写真補正ツールや補正技法についても情報提供しています。写真補正技法への質問はコメント欄へどうぞ

文字列に、文字データを挿入しようとしたら... Pythonプログラミング Tips

 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 から始まる言語に慣れていましたので、引っ掛かってしまったのでした。新しくコンピュータ言語を勉強される方は、こんなところで引っかからないでしょう。自分の備忘録として記しておきます。