1. ホーム
  2. python

なぜPythonはシーケンスに対して範囲外のスライスインデックスを許すのですか?

2023-11-03 20:35:17

質問

私はちょうどPythonの奇妙な機能のように思えるものに出くわしたので、それについていくつかの明確化を望んでいました。

次の配列操作は、いくらか意味があります。

p = [1,2,3]
p[3:] = [4] 
p = [1,2,3,4]

実際にはこの値を最後に追加しているだけだと想像しますが、いかがでしょうか?

しかしながら、なぜこのようなことができるのでしょうか?

p[20:22] = [5,6]
p = [1,2,3,4,5,6]

そして、さらにこんなことも。

p[20:100] = [7,8]
p = [1,2,3,4,5,6,7,8]

これは間違ったロジックのように思えます。これはエラーを投げるべきように思えます!

何か説明がありますか?

-それはちょうどPythonが行う奇妙なことですか?

-何か目的があるのでしょうか?

-それとも、私の考え方が間違っているのでしょうか?

どのように解決するのですか?

範囲外の指数に関する質問の一部

スライスロジックは自動的にインデックスをシーケンスの長さに合わせて切り取ります。

スライスインデックスが終点を超えて拡張することを許可するのは、利便性のために行われました。 すべての式を範囲チェックして、手動で制限を調整しなければならないのは面倒なので、Pythonがあなたのためにそれを行います。

テキストメッセージの最初の50文字より多くを表示したくないというユースケースを考えてみましょう。

簡単な方法(Pythonが今やっていること)。

preview = msg[:50]

または、難しい方法(自分でリミットチェックをする)。

n = len(msg)
preview = msg[:50] if n > 50 else msg

終点の調整のためにそのロジックを手動で実装することは、忘れやすく、間違えやすく(2か所で50を更新する)、言葉が多くなり、遅くなります。 Pythonはそのロジックを内部に移動させ、簡潔で、自動的で、速く、そして正しいものにします。 これは私がPythonを愛する理由の1つです:-)

入力の長さからの代入の長さの不一致に関する質問の部分

OP はまた、次のような割り当てを許可する根拠を知りたがっていました。 p[20:100] = [7,8] のような割り当てを許可する根拠についても知りたいと考えていました。

文字列との類似によって動機を見るのが最も簡単です。 考えてみましょう。 "five little monkeys".replace("little", "humongous") . ターゲットの "little" は6文字しかなく、 "humongous" は9文字であることに注意してください。 リストでも同じことができます。

>>> s = list("five little monkeys")
>>> i = s.index('l')
>>> n = len('little')
>>> s[i : i+n ] = list("humongous")
>>> ''.join(s)
'five humongous monkeys'

これはすべて利便性のためです。

が導入される以前は copy() clear() メソッドがあり、これらは以前はよく使われたイディオムでした。

s[:] = []           # clear a list
t = u[:]            # copy a list

現在でも、フィルタリングの際にリストを更新するために使用しています。

s[:] = [x for x in s if not math.isnan(x)]   # filter-out NaN values

これらの実用例が、なぜスライスが機能するのかについて良い見通しを与えてくれることを願っています。