1文字の文字列で、2番目の文字をフェッチしようとすると、Pythonは非常に詳細に失敗します。これは正しく、予想される動作です。
print 'a'[1]
ただし、無効なサブシーケンス範囲をフェッチしようとすると、サイレントに失敗します。
print 'a'[1:]
行動の違いの理由は何ですか?
1文字の文字列で、2番目の文字をフェッチしようとすると、Pythonは非常に詳細に失敗します。これは正しく、予想される動作です。
print 'a'[1]
ただし、無効なサブシーケンス範囲をフェッチしようとすると、サイレントに失敗します。
print 'a'[1:]
行動の違いの理由は何ですか?
andの場合、実際にslicing
は何も生成しません:error
strings
lists
たとえば。
>>> s='abc'
>>> s[-1000:1000]
'abc'
正常に動作します。
一方、Indexes
定義されていないものにアクセスすると、常に and の両方で anがIndexError
発生します。strings
lists
>>> s[4]
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
s[4]
IndexError: string index out of range
これは、リストの変更可能なスライスがどのように動作するかを見ると、より理にかなっています。
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[10] = 2
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
a[10] = 2
IndexError: list assignment index out of range
>>> a[10:] = [1, 2, 3]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]
スライスの末尾を超えて変更すると、新しい値が末尾に追加されます。これは、行うのと同じa.extend([1, 2, 3])
です (ただし、開始点が存在する場合は少し異なります)。理解すれば、これは驚くべきことではありません。
>>> a = list(range(10))
>>> a[2:4] = range(10)
>>> a
[0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9]
しかし、このスライスを変更することができるので、これにアクセスしようとすると少し驚くでしょうIndexError
- 言語のどこにもあなたが設定できるものを取得することはありません 以外のもので失敗しますNameError
。しかし、NameError
ここでは意味がありません。Pythonは正しい名前のオブジェクトを見つけ、そのオブジェクトに対してメソッドを呼び出しました。
そのため、Python はリストの最後を超えたスライスをエラーとは見なしません。それを念頭に置いて、スライスへのアクセスが組み込みシーケンス間で異なる動作をする必要があるのはなぜですか? 文字列 (およびタプル) は不変であるため、スライスの割り当ては常に失敗しますが、そこにある値を確認することは突然変異ではありません。
したがって、実際には、最終的な理由は、この動作が他の考えられる動作よりも驚くべきことではないと開発者が感じたからです。
セマンティクスが異なります。
print 'a'[1]
存在しない (無効な) インデックス/場所にインデックスを作成しようとしますが、これはエラーです。
print 'a'[1:]
指定された範囲に基づいて、エラーではない''
空の文字列 ( ) を返すだけです。
すなわち、
In [175]: 'a'[1]
---------------------------------------------------------------------------
----> 1 'a'[1]
IndexError: string index out of range
In [176]: 'a'[1:]
Out[176]: ''
スライス操作はインデックス操作とは異なります。インデックスは要素を返し、スライスは空の範囲や空の文字列であっても範囲を返します。
要素が 1 つの配列には、インデックス ポインターが 0 と 1 の 2 つの「境界」があります。スライス'a'[0:1]
して、これらの位置の間にある文字列 (またはリストまたは配列の範囲) を取得できます。
左端の境界線から最後までスライスすると、読み取りは既にある最後まで進み、空の文字列が得られます。
次のように考えられます。
を使用する場合a[1]
、アクセスしたいもの (この場合は文字列の 2 番目の要素) を正確に知っていると想定されます。a[1]
存在しないため、python は例外を発生させます。
ただし、範囲演算子a[1:]
は、データの正確な範囲がわからない可能性があるセマンティクスで実装されているため、非常に大きなインデックス (ランダムな推測) を指定しても、文字列 (またはシーケンス) の有効な部分を取得できます。この場合に空の文字列を取得する理由は、この範囲内の文字列に要素がないためですa[1:]
。
お役に立てれば。