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


90

なぜ'example'[999:9999]エラーが発生しないのですか?それ以来'example'[9]、その背後にある動機は何ですか?

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


17
[999:9999]はインデックスではなく、スライスであり、セマンティクスが異なります。Pythonのイントロから:「縮退したスライスインデックスは適切に処理されます。大きすぎるインデックスは文字列サイズに置き換えられ、下限よりも小さい上限は空の文字列を返します。」
ウーブル2012

2
@Woobleが実際の答えです
jondavidjohn 2012

2
@Woobleそして、なぜそれがこのようになっているのか知っていますか?ご説明ありがとうございます。
ijverig 2012

どうして?Guidoに聞いてみる必要がありますが、スライスが常に元のシーケンスと同じタイプのシーケンスであると想定できるのはエレガントだと思います。
ウーブル2012

1
@Lapinotはいこの動作に依存するコードを作成しました。残念ながら、正確なコードを思い出せないので、理由を説明できません。おそらく部分文字列と関係がありました。空の文字列を取得することは、ときどき必要なことです。
マークランサム

回答:


69

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

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

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

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

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

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


1
範囲外のインデックスNoneは、エラーではなく返される可能性があります。これは、返されるものがない場合の通常のPythonの規則です。
マークランサム

8
@MarkRansom、それは本当です。ただしNone、この場合に戻ると、範囲外のインデックスとNoneリスト内の値を区別するのが難しくなります。しかし、その回避策があったとしても、範囲外のスライスが与えられた場合、空のシーケンスを返すことが正しいことであることは私には明らかです。これは、2つの互いに素なセットの和集合を実行することに似ています。
センダール2012

明確にするために、私はあなたが間違っているとは言いませんでした。Noneリストの値についてのあなたのポイントがわかります。
マークランサム

1
@MarkRansom、私は知っています-私が防御的に聞こえたらごめんなさい。本当に私は集合論を参照する言い訳が欲しかったのです:)。
センダール2012

4
ああ、「交差点」ではなく「結合」と言った以外は。
センダール2014

33

ドキュメントの堅牢なセクションを指す回答を追加するために:

のようなスライス式が与えられるとs[i:j:k]

ステップkでのiからjまでのsのスライスは、次ようなインデックスを持つアイテムのシーケンスとして定義されます。つまり、インデックスがあり、、、ときなど、停止jが到達している(しかし、決して含めないJ)。kが正の場合ijは大きい場合に縮小されます。x = i + n*k0 <= n < (j-i)/kii+ki+2*ki+3*klen(s)

と書くとs[999:9999]s[len(s):len(s)]それ以降Pythonが返され、len(s) < 999ステップは正になります(1-デフォルト)。


おそらく、kが正の場合、iそしてそれらが小さい場合にjも増加し-len(s)ますか?例s = 'bac'; s[-100:2] == s[-len(s):2]
Chris_Rands 2017

@Chris_Randskが正の場合、Pythonはスケーリングij、シーケンスの境界に合うようにします。あなたの例では、s[-100:2] == s[0:2]== s[-len(s):2]ちなみに)。同様に、s[-100:100] == s[0:2]
tylerc0816 2017

よかった、ありがとう。これは、上記の@speedplaneのコメントに対するより良い応答です。
センダール2018

8

スライスは制限されていません-組み込みのタイプによってチェックされます。また、両方の例で同じ結果が得られているように見えますが、動作は異なります。代わりにリストで試してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.