web-dev-qa-db-ja.com

インデックスが範囲外の部分文字列スライスが機能するのはなぜですか?

'example'[999:9999]がエラーにならないのはなぜですか? 'example'[9]はそうするので、その背後にある動機は何ですか?

この振る舞いから、'example'[3]は、本質的に/内部的に、'example'[3:4]と同じではなく、両方とも同じ'm'文字列になります。

65
ijverig

正解です! 'example'[3:4]および'example'[3]は根本的に異なり、シーケンスの境界の外側(少なくとも組み込みの場合)をスライスしてもエラーは発生しません。

最初は驚くかもしれませんが、考えてみると理にかなっています。インデックス付けは単一のアイテムを返しますが、スライスはアイテムのサブシーケンスを返します。したがって、存在しない値にインデックスを付けようとしても、返すものは何もありません。ただし、シーケンスを境界外にスライスすると、空のシーケンスを返すことができます。

ここで混乱しているのは、文字列の動作がリストとは少し異なることです。リストに対して同じことを行うとどうなるか見てみましょう。

>>> [0, 1, 2, 3, 4, 5][3]
3
>>> [0, 1, 2, 3, 4, 5][3:4]
[3]

ここで違いは明らかです。文字列の場合、Pythonには文字列の外側に個々の文字のようなものがないため、結果は同じように見えます。単一の文字は、1文字の文字列です。

(シーケンスの範囲外のスライスの正確なセマンティクスについては、 mgilson's answer を参照してください。)

52
senderle

documentation の堅牢なセクションを指す回答を追加するために:

s[i:j:k]のようなスライス式が与えられた場合、

ステップkを使用したsのiからjへのスライスは、0 <= n <(j-i)/ kとなるようなインデックスx = i + n * kのアイテムのシーケンスとして定義されます。つまり、インデックスはi、i + k、i + 2 * k、i + 3 * kなどであり、jに到達すると停止します(jは含まれません)。 kが正の場合、iとjが大きい場合、len(s)に縮小されます

s[999:9999]と書いた場合、pythonはs[len(s):len(s)]でステップが正であるためlen(s) < 999を返します(1-デフォルト)。

22
mgilson

スライスは、組み込み型によって境界チェックされません。また、どちらの例も同じ結果に見えますが、動作は異なります。代わりにリストで試してください。