web-dev-qa-db-ja.com

pythonスライスによる奇妙な動作

次のリストがあるとします。

>>> a = [x for x in range(10)]
>>> print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

それとは別に、期待どおりに作業をスライスする両方の方法:

>>> a[3:8]
[3, 4, 5, 6, 7]

>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

しかし、組み合わせると:

>>> a[3:8:-1]
[]

私はそれが[7, 6, 5 ,4, 3] 多分 [6, 5, 4, 3, 2](逆転が最初に発生した場合)。 startまたはstopパラメータが渡されなかった場合に何が起こるかを検討することも興味深いです。

>>> a[:5:-1]
[9, 8, 7, 6]

これは私が予想するものとほぼ同じで、1つのアイテムだけが不足しています。これをnumpyでテストすると、同じように動作するようです。

何が起きてる?

18
user3105173

a[3:8:-1]

スライスの開始位置と停止位置は、ステップに基づいて調整されません。負のステップでは、3から逆方向に進みますが、3から逆算して3から8の範囲のインデックスを持つ要素がないため、空のリストが取得されます。

開始と停止を適宜設定する必要があります。

a[8:3:-1]

8から4にカウントされます。

19
Carcigenicate

_a[3:8:-1]_はpythonを3から開始し、-1のステップで8に移動するように指示します

これは空のリストを作成します:_-1_を追加して3から8に到達することはできません(空のリストも与えるlist(range(3,8,-1))のように)

_a[:5:-1]_を実行すると、startがデフォルトの開始となり、pythonは「リストの終わり」に設定されるため、「機能します」

_a[::-1]_を実行する場合と同じですが、開始と停止はデフォルトのものであり、pythonは、それらが最後から最初までであることを理解します(そうでない場合、この表記は使用できません)

この動作は ドキュメント で説明されています。

Sのiからjへのスライスは、i <= k <jとなるようなインデックスkを持つアイテムのシーケンスとして定義されます。 iまたはjがlen(s)より大きい場合は、len(s)を使用します。 iを省略するかNoneの場合は0を使用します。jを省略するかNoneの場合はlen(s)を使用します。 iがj以上の場合、スライスは空です。

ステップkでiからjへのsのスライス。jに到達すると停止します(ただしjは含まれません)。 kが正の場合、iとjは、大きい場合はlen(s)に削減されます。 kが負の場合、iとjは、大きい場合はlen(s)-1に削減されます。 iまたはjが省略されるか、Noneの場合、それらは「終了」値になります(終了はkの符号に依存します)。

4
sammy