スライス表記について


3284

Pythonのスライス表記について、良い説明が必要です(参照はプラスです)。

私にとって、この表記は少しピックアップする必要があります。

非常にパワフルに見えますが、頭がよくわかりません。

回答:


4505

とてもシンプルです:

a[start:stop]  # items start through stop-1
a[start:]      # items start through the rest of the array
a[:stop]       # items from the beginning through stop-1
a[:]           # a copy of the whole array

step上記のいずれかで使用できる値もあります。

a[start:stop:step] # start through not past stop, by step

覚えておくべき重要な点は、:stop値は選択されたスライスにない最初の値を表すということです。だから、差stopとは、start選択された要素の数は、(もしありますstep 1、デフォルトです)。

もう1つの機能は、その値であるstartstop負の数になる場合があります。つまり、配列の先頭ではなく、末尾から数えます。そう:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

同様に、step負の数の場合もあります:

a[::-1]    # all items in the array, reversed
a[1::-1]   # the first two items, reversed
a[:-3:-1]  # the last two items, reversed
a[-3::-1]  # everything except the last two items, reversed

あなたが要求するよりも項目が少ない場合、Pythonはプログラマーに親切です。たとえばa[:-2]a要素が1つしか含まない、エラーではなく空のリストが表示されます。時々あなたはエラーを好むので、あなたはこれが起こるかもしれないことに気づく必要があります。

との関係 slice()オブジェクトとの

[]上記のコードでは、スライス演算子は実際にslice():表記法(内でのみ有効[])を使用するオブジェクトとともに使用されています。つまり、

a[start:stop:step]

以下と同等です。

a[slice(start, stop, step)]

スライスオブジェクトも、と同様にrange()、引数の数に応じて動作が少し異なります。つまり、slice(stop)との両方slice(start, stop[, step])がサポートされています。特定の引数の指定をスキップするには、を使用する場合があります。Noneたとえば、はとa[start:]同等a[slice(start, None)]またはa[::-1]と同等a[slice(None, None, -1)]です。

ながら:ベース表記は、単純なスライシングのために非常に有用である、の明示的な使用slice()目的は、スライスのプログラム生成を単純化します。


122
組み込み型をスライスするとコピーが返されますが、これは一般的ではありません。特に、NumPy配列をスライスすると、元のメモリとメモリを共有するビューが返されます。
Beni Cherniavsky-Paskin 2013

43
これはそれを証明するための投票での美しい答えですが、それは一つのことを逃しています:あなたNoneは空のスペースのどれでも代用することができます。たとえば[None:None]、全体のコピーを作成します。これは、変数を使用して範囲の終わりを指定する必要があり、最後の項目を含める必要がある場合に役立ちます。
Mark Ransom

6
私を本当に困らせているのは、Pythonが開始と終了を設定しない場合、デフォルトで0でシーケンスの長さになると言っていることです。したがって、理論的には、「abcdef」[::-1]を使用する場合、「abcdef」[0:6:-1]に変換する必要がありますが、これらの2つの式は同じ出力を取得しません。言語の作成以来、Pythonのドキュメントに何かが欠けているように感じます。
axell13

6
そして、「abcdef」[::-1]が「abcdef」[6:-7:-1]に変換されることを知っているので、説明する最良の方法は、lenをシーケンスの長さとすることです。stepが正の場合、startおよびendのデフォルトは0およびlenです。そうでなければステップが否定的である場合、開始と終了のためのデフォルト値がされたlenおよび- lenの - 1
axell13

4
stackoverflow.com/questions/39241529/…はこれの重複としてマークされているので、delスライス表記についてのセクションを追加することは理にかなっていますか?特に、del arr[:]すぐにはわかりません(「arr [:]はコピーを作成するため、delはそのコピーを削除しますか???」など)
khazhyk

538

Pythonのチュートリアルそれについての協議(スクロールビットダウンあなたは、スライスに関する部分を取得するまで)。

ASCIIアート図は、スライスがどのように機能するかを覚えておくのにも役立ちます。

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

スライスがどのように機能するかを覚える1つの方法は、インデックスを文字を指すと考え、最初の文字の左端を0と番号付けすることです。次に、n文字の文字列の最後の文字の右端はインデックスnを持ちます。


10
この提案はポジティブストライドに対しては機能しますが、ネガティブストライドに対しては機能しません。図から、私はそうであると期待a[-4,-6,-1]していますyPが、そうですty。常に機能するのは、文字またはスロットを考慮し、インデックスをハーフオープンインターバルとして使用することです。正のストライドの場合は右オープン、負のストライドの場合は左オープンです。
aguadopd

ただし、最初から空のセットに折りたたむ方法はないため(x[:0]最初から開始する場合のように)、特殊なケースの小さな配列を使用する必要があります。:/
エンドリス

412

文法が許す可能性を列挙する:

>>> seq[:]                # [seq[0],   seq[1],          ..., seq[-1]    ]
>>> seq[low:]             # [seq[low], seq[low+1],      ..., seq[-1]    ]
>>> seq[:high]            # [seq[0],   seq[1],          ..., seq[high-1]]
>>> seq[low:high]         # [seq[low], seq[low+1],      ..., seq[high-1]]
>>> seq[::stride]         # [seq[0],   seq[stride],     ..., seq[-1]    ]
>>> seq[low::stride]      # [seq[low], seq[low+stride], ..., seq[-1]    ]
>>> seq[:high:stride]     # [seq[0],   seq[stride],     ..., seq[high-1]]
>>> seq[low:high:stride]  # [seq[low], seq[low+stride], ..., seq[high-1]]

もちろん、の場合(high-low)%stride != 0、エンドポイントはより少し低くなりhigh-1ます。

strideが負の場合、カウントダウンしているため、順序が少し変更されます。

>>> seq[::-stride]        # [seq[-1],   seq[-1-stride],   ..., seq[0]    ]
>>> seq[high::-stride]    # [seq[high], seq[high-stride], ..., seq[0]    ]
>>> seq[:low:-stride]     # [seq[-1],   seq[-1-stride],   ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]

拡張スライシング(コンマと楕円を使用)は、主に特別なデータ構造(NumPyなど)でのみ使用されます。基本シーケンスはそれらをサポートしていません。

>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'

実際にはまだ何かが残っています。たとえば、「apple」[4:-4:-1]と入力すると、「elp」が表示され、Pythonは-4を1に変換しているのでしょうか。
liyuan

バックrepr
ティック

@liyuan実装するタイプ__getitem__は次のとおりです。あなたの例はと同等apple[slice(4, -4, -1)]です。
chepner

320

上記の回答では、スライスの割り当てについては説明していません。スライスの割り当てを理解するには、ASCIIアートに別の概念を追加すると便利です。

                +---+---+---+---+---+---+
                | P | y | t | h | o | n |
                +---+---+---+---+---+---+
Slice position: 0   1   2   3   4   5   6
Index position:   0   1   2   3   4   5

>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
 'P'
>>> p[5]
 'n'

# Slicing gives lists
>>> p[0:1]
 ['P']
>>> p[0:2]
 ['P','y']

1つのヒューリスティックは、0からnまでのスライスについて、「ゼロは最初から始まり、最初から始まり、リスト内のn項目を取る」と考えます。

>>> p[5] # the last of six items, indexed from zero
 'n'
>>> p[0:5] # does NOT include the last item!
 ['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
 ['P','y','t','h','o','n']

別のヒューリスティックは、「すべてのスライスについて、開始をゼロで置き換え、前のヒューリスティックを適用してリストの終わりを取得し、最初の数をカウントして最初から数え直してアイテムを切り取る」です。

>>> p[0:4] # Start at the beginning and count out 4 items
 ['P','y','t','h']
>>> p[1:4] # Take one item off the front
 ['y','t','h']
>>> p[2:4] # Take two items off the front
 ['t','h']
# etc.

スライス割り当ての最初のルールは、スライスするとリストが返されるため、スライス割り当てにリスト(または他の反復可能)が必要であることです。

>>> p[2:3]
 ['t']
>>> p[2:3] = ['T']
>>> p
 ['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable

スライス割り当ての2番目のルールは、上記でも確認できますが、リストのどの部分もスライスインデックスによって返されます。これは、スライス割り当てによって変更される部分と同じです。

>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

スライス割り当ての3番目のルールは、割り当てられたリスト(反復可能)が同じ長さである必要がないことです。インデックスが付けられたスライスは単純にスライスされ、割り当てられているものでまとめて置き換えられます。

>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
 ['P','y','s','p','a','m','o','n']

慣れるのが最も難しい部分は、空のスライスへの割り当てです。ヒューリスティック1と2を使用すると、空のスライスにインデックスを付けるのが簡単になります。

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []

そして、それを見たら、空のスライスへのスライスの割り当ても意味があります。

>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
 ['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
 ['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
 ['P','y','t','h','x','y','o','n'] # The result is longer still

スライスの2番目の数(4)は変更しないため、空のスライスに割り当てている場合でも、挿入されたアイテムは常に「o」に対してスタックされます。したがって、空のスライス割り当ての位置は、空でないスライス割り当ての位置を論理的に拡張したものです。

少しバックアップすると、スライスの開始を数えるという私たちの行列を続けているとどうなりますか?

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []

スライシングを使用すると、完了したら完了です。逆方向にスライスし始めません。Pythonでは、負の数を使用して明示的に要求しない限り、負のストライドは得られません。

>>> p[5:3:-1]
 ['n','o']

「完了したら、完了」ルールには、いくつかの奇妙な結果があります。

>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []
>>> p[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

実際、索引付けと比較して、Pythonのスライシングは奇妙にエラーを防止します。

>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

これはときどき役に立ちますが、奇妙な動作につながることもあります:

>>> p
 ['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
 ['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']

アプリケーションに応じて、それは...そうでないかもしれません...あなたがそこに望んでいたことです!


以下は私の元の答えのテキストです。多くの人に役立ったので、削除したくありませんでした。

>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]

これにより、スライスとインデックスの違いも明確になります。


246

Pythonのスライス表記について説明する

要するに、コロン(:添字表記)( subscriptable[subscriptarg])メイクスライス表記-オプションの引数を有し、startstopstep

sliceable[start:stop:step]

Pythonスライシングは、データの一部に系統的にアクセスするための計算上高速な方法です。私の意見では、中級のPythonプログラマであることは、言語に精通している必要があることの1つの側面です。

重要な定義

まず、いくつかの用語を定義しましょう。

start:スライスの開始インデックス。stopと同じでない限り、このインデックスの要素が含まれます。デフォルトは0、つまり最初のインデックスです。負の値の場合は、n項目を最後から開始することを意味します。

stop:スライスの終了インデックス。このインデックスの要素含まれませ。デフォルトでは、スライスされるシーケンスの長さ、つまり終了までの長さになります。

ステップ:インデックスが増加する量。デフォルトは1です。負の場合は、イテラブルを逆方向​​にスライスします。

インデックス作成のしくみ

これらの正数または負数のいずれかを作成できます。正の数の意味は簡単ですが、Pythonのインデックスと同様に、負の数の場合は、startstopの末尾から逆方向にカウントし、stepの場合は、インデックスをデクリメントします。この例はドキュメンテーションのチュートリアルからのものですが、各インデックスが参照するシーケンス内のアイテムを示すように少し変更しました。

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

スライスのしくみ

サポートするシーケンスでスライス表記を使用するには、シーケンスに続く角括弧に少なくとも1つのコロンを含める必要があります(これは、Pythonデータモデルに従って、実際にシーケンス__getitem__メソッドを実装します)。

スライス表記は次のように機能します。

sequence[start:stop:step]

また、startstopstepにはデフォルトがあるため、デフォルトにアクセスするには、引数を省略してください。

リスト(または文字列など、それをサポートするその他のシーケンス)から最後の9つの要素を取得するためのスライス表記は次のようになります。

my_list[-9:]

これを見ると、括弧内の部分を「終わりから9番目、終わりまで」と読みます。(実際には、精神的には「-9、on」と略しています)

説明:

完全な表記は

my_list[-9:None:None]

そして、デフォルトを置き換えるには(実際にstepはが負の場合、stopのデフォルトは-len(my_list) - 1なのでNone、停止の場合は、実際には、終了ステップのいずれかが実行されることを意味します):

my_list[-9:len(my_list):1]

コロンは:あなたがそれをスライスしていない通常のインデックスを与えているのPythonを告げるものです。そのため、Python 2でリストの浅いコピーを作成する慣用的な方法は、

list_copy = sequence[:]

そしてそれらをクリアすることで:

del my_list[:]

(Python 3はlist.copyおよびlist.clearメソッドを取得します。)

step負である、のデフォルト値startおよびstop変更

デフォルトでは、step引数が空(またはNone)の場合、に割り当てられ+1ます。

ただし、負の整数を渡すと、リスト(または他のほとんどの標準スライス)が最後から最初にスライスされます。

したがって、負のスライスはstartおよびのデフォルトを変更しますstop

ソースでこれを確認する

私はユーザーにソースとドキュメントを読むことを勧めたいと思います。スライスオブジェクトとこのロジックソースコードはここにあります。まず、stepが負かどうかを判断します。

 step_is_negative = step_sign < 0;

もしそうなら、下限-1 は最初までをスライスすることを意味し、上限は長さから1を引いたもので、最後から開始することを意味します。(注:これの意味はこと-1異なるから-1、ユーザーが最後の項目を示すPythonでインデックスを渡すことができること。)

if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;

    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

それ以外の場合stepは正であり、下限はゼロ、上限はスライスリストの長さになります(上限は含まれません)。

else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

次に、startand のデフォルトを適用する必要がある場合があります。-のデフォルトは、が負の場合に上限として計算されstopます。startstep

if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

そしてstop、下限:

if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

スライスにわかりやすい名前を付けてください!

list.__getitem__メソッドに渡すことからスライスを形成することを分離することは便利かもしれません(それが角括弧がすることです)。初めての方でも、コードを読みやすくすることで、コードを読む必要のある他のユーザーがあなたが何をしているかをより簡単に理解できるようになります。

ただし、コロンで区切られた整数を変数に割り当てることはできません。スライスオブジェクトを使用する必要があります。

last_nine_slice = slice(-9, None)

第二引数は、None最初の引数として解釈されるように、必要とされるstart引数そうでない場合は次のようになりstop、引数

次に、スライスオブジェクトをシーケンスに渡すことができます。

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

範囲もスライスを取るのは興味深いことです。

>>> range(100)[last_nine_slice]
range(91, 100)

メモリに関する考慮事項:

Pythonリストのスライスはメモリ内に新しいオブジェクトを作成するので、注意すべきもう1つの重要な関数はitertools.isliceです。通常、メモリ内で静的に作成するだけでなく、スライスを反復処理する必要があります。isliceこれに最適です。注意点は、それが負の引数をサポートしていませんstartstopまたはstep、それが問題だもしそうなら、あなたはインデックスを計算したり、事前に反復可能を逆にする必要があるかもしれませんが。

length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

そしていま:

>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

リストのスライスがコピーを作成するという事実は、リスト自体の機能です。Pandas DataFrameなどの高度なオブジェクトをスライスする場合、コピーではなく元のビューが返されることがあります。


147

そして、スライシング構文を最初に見たとき、すぐにはわからなかったいくつかのこと:

>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

シーケンスを逆にする簡単な方法!

そして、あなたが望むなら、何らかの理由で、逆の順序で2つおきの項目:

>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]

100

Python 2.7の場合

Pythonでのスライス

[a:b:c]

len = length of string, tuple or list

c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.

a --  When c is positive or blank, default is 0. When c is negative, default is -1.

b --  When c is positive or blank, default is len. When c is negative, default is -(len+1).

インデックスの割り当てを理解することは非常に重要です。

In forward direction, starts at 0 and ends at len-1

In backward direction, starts at -1 and ends at -len

[a:b:c]と言うときは、cの符号(前方または後方)に応じて、aで始まり、bで終わります(b番目のインデックスの要素を除く)。上記のインデックス作成ルールを使用して、この範囲の要素のみが見つかることを覚えておいてください。

-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

ただし、この範囲は両方向に無限に続きます。

...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

例えば:

             0    1    2   3    4   5   6   7   8   9   10   11
             a    s    t   r    i   n   g
    -9  -8  -7   -6   -5  -4   -3  -2  -1

上記のa、b、cのルールを使用してトラバースするときに、a、b、cの選択が上記の範囲とのオーバーラップを許可する場合、要素を含むリスト(トラバース中にタッチ)を取得するか、空のリストを取得します。

最後に、aとbが等しい場合、空のリストも取得します。

>>> l1
[2, 3, 4]

>>> l1[:]
[2, 3, 4]

>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]

>>> l1[:-4:-1] # a default is -1
[4, 3, 2]

>>> l1[:-3:-1] # a default is -1
[4, 3]

>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]

>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]


>>> l1[-100:-200:-1] # Interesting
[]

>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]


>>> l1[-1:-1:1]
[]


>>> l1[-1:5:1] # Interesting
[4]


>>> l1[1:-7:1]
[]

>>> l1[1:-7:-1] # Interesting
[3, 2]

>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]

2
別の興味深い例:a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]結果は[9]
Deviacium

96

http://wiki.python.org/moin/MovingToPythonFromOtherLanguagesでこの素晴らしいテーブルを見つけました

Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.

Index from rear:    -6  -5  -4  -3  -2  -1      a=[0,1,2,3,4,5]    a[1:]==[1,2,3,4,5]
Index from front:    0   1   2   3   4   5      len(a)==6          a[:5]==[0,1,2,3,4]
                   +---+---+---+---+---+---+    a[0]==0            a[:-2]==[0,1,2,3]
                   | a | b | c | d | e | f |    a[5]==5            a[1:2]==[1]
                   +---+---+---+---+---+---+    a[-1]==5           a[1:-1]==[1,2,3,4]
Slice from front:  :   1   2   3   4   5   :    a[-2]==4
Slice from rear:   :  -5  -4  -3  -2  -1   :
                                                b=a[:]
                                                b==[0,1,2,3,4,5] (shallow copy of a)

65

少し使ってみたところ、最も簡単な説明は、forループ内の引数とまったく同じであることがわかりました...

(from:to:step)

それらはいずれもオプションです。

(:to:step)
(from::step)
(from:to)

次に、負のインデックス付けでは、文字列の長さを負のインデックスに追加して理解する必要があります。

これはとにかく私のために働く...


52

私はそれがどのように機能するか覚えるのがより簡単であるとわかり、それから私は特定のスタート/ストップ/ステップの組み合わせを理解することができます。

range()最初に理解することは有益です:

def range(start=0, stop, step=1):  # Illegal syntax, but that's the effect
    i = start
    while (i < stop if step > 0 else i > stop):
        yield i
        i += step

から始まりstart、増加しstep、到達しませんstop。とてもシンプル。

否定的なステップについて覚えておくべきことstopは、それが高いか低いかにかかわらず、常に除外された端であるということです。同じスライスを逆の順序にしたい場合は、逆に個別に行うほうがはるかにクリーンです。たとえば'abcde'[1:-2][::-1]、左から1文字、右から2文字をスライスしてから逆にします。(も参照してくださいreversed()。)

シーケンスのスライスは同じですが、最初に負のインデックスを正規化し、シーケンスの外には出られません。

TODO:以下のコードには、abs(step)> 1のときに「シーケンスの外に出ない」というバグがありました。私が考えて、私はそれが正しいようにパッチを適用しますが、それは理解することが難しいです。

def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
    if start is None:
        start = (0 if step > 0 else len(seq)-1)
    elif start < 0:
        start += len(seq)
    if not 0 <= start < len(seq):  # clip if still outside bounds
        start = (0 if step > 0 else len(seq)-1)
    if stop is None:
        stop = (len(seq) if step > 0 else -1)  # really -1, not last element
    elif stop < 0:
        stop += len(seq)
    for i in range(start, stop, step):
        if 0 <= i < len(seq):
            yield seq[i]

is None詳細については心配しないでください。シーケンス全体を提供するために省略startしたり、stop常に正しいことを行ったりすることを忘れないでください。

:正規負のインデックスは、最初の開始及び/又は停止は、独立して、端から数えされることを可能にする'abcde'[1:-2] == 'abcde'[1:3] == 'bc'にもかかわらずrange(1,-2) == []。正規化は「長さを法として」と考えられることがありますが、長さは1回だけ追加され'abcde'[-53:42]ます。たとえば、文字列全体です。


3
これthis_is_how_slicing_worksはpythonスライスと同じではありません。EG [0, 1, 2][-5:3:3]はPythonでは[0]を取得しますがlist(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))、[1]を取得します。
Eastsun

@Eastsunおっと、あなたは正しいです!より明確なケース:range(4)[-200:200:3] == [0, 3]しかしlist(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]。私if 0 <= i < len(seq):は単に「シーケンスの外に出ない」を実装しようとする試みでしたが、ステップ> 1では間違っています。今日は後で(テストを含めて)書き直します。
Beni Cherniavsky-Paskin

40

私はそれについて自分で考える「要素間のインデックスポイント」方式を使用していますが、それを説明する1つの方法は、他の人がそれを理解するのに役立つ場合があります。

mylist[X:Y]

Xは、必要な最初の要素のインデックスです。
Yは、あなたが最初の要素のインデックスではありませんします。


40
Index:
      ------------>
  0   1   2   3   4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
  0  -4  -3  -2  -1
      <------------

Slice:
    <---------------|
|--------------->
:   1   2   3   4   :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
:  -4  -3  -2  -1   :
|--------------->
    <---------------|

これがPythonでリストをモデル化するのに役立つことを願っています。

リファレンス:http : //wiki.python.org/moin/MovingToPythonFromOtherLanguages


38

Pythonスライス表記:

a[start:end:step]
  • ためstartend、負の値は、シーケンスの最後まで相対ものとして解釈されます。
  • の正のインデックスendは、含まれる最後の要素のの位置を示します。
  • 空白の値のデフォルトは次のとおりです[+0:-0:1]
  • 負のステップを使用すると、startおよびの解釈が逆になりますend

表記法は、(numpy)行列および多次元配列に拡張されます。たとえば、列全体をスライスするには、次のように使用できます。

m[::,0:2:] ## slice the first two columns

スライスは、配列要素のコピーではなく参照を保持します。別のコピーを配列にしたい場合は、を使用できますdeepcopy()


34

スライス割り当てを使用して、リストから1つ以上の要素を削除することもできます。

r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]

33

これは追加情報のためだけです...以下のリストを検討してください

>>> l=[12,23,345,456,67,7,945,467]

リストを逆にするためのその他のトリックはほとんどありません。

>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

33

これは私が初心者にスライスを教える方法です:

インデックス付けとスライスの違いを理解する:

Wiki Pythonには、インデックス作成とスライスを明確に区別するこの素晴らしい画像があります。

ここに画像の説明を入力してください

6つの要素を含むリストです。スライスについて理解を深めるために、そのリストを6つのボックスを1つにまとめたものと考えてください。各ボックスにはアルファベットが含まれています。

インデックス作成は、ボックスの内容を処理するようなものです。ボックスの内容を確認できます。ただし、複数のボックスの内容を一度に確認することはできません。ボックスの内容物を交換することもできます。ただし、1つのボックスに2つのボールを入れることも、2つのボールを一度に交換することもできません。

In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']

In [124]: alpha[0]
Out[124]: 'a'

In [127]: alpha[0] = 'A'

In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']

In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]

TypeError: list indices must be integers, not tuple

スライスは、ボックス自体を処理するようなものです。最初のボックスを取り出して、別のテーブルに置くことができます。箱を手に取るには、箱の始まりと終わりの位置を知るだけです。

最初の3つのボックス、最後の2つのボックス、または1から4までのすべてのボックスを選択することもできます。したがって、開始と終了がわかっている場合は、任意のボックスセットを選択できます。これらの位置は、開始位置と停止位置と呼ばれます。

興味深いのは、一度に複数のボックスを交換できることです。また、複数のボックスを好きな場所に配置できます。

In [130]: alpha[0:1]
Out[130]: ['A']

In [131]: alpha[0:1] = 'a'

In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']

In [133]: alpha[0:2] = ['A', 'B']

In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']

In [135]: alpha[2:2] = ['x', 'xx']

In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']

ステップによるスライス:

今まで、あなたは継続的に箱を選びました。しかし、時々、個別にピックアップする必要があります。たとえば、1つおきのボックスを選択できます。ボックスの最後から3つおきに受け取ることもできます。この値はステップサイズと呼ばれます。これは、連続するピックアップ間のギャップを表しています。最初から最後までボックスを選択する場合、またはその逆の場合、ステップサイズは正でなければなりません。

In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']

In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']

In [144]: alpha[1:5:-2]
Out[144]: []

In [145]: alpha[-1:-5:2]
Out[145]: []

Pythonが欠落しているパラメーターを計算する方法:

スライスするときに、パラメーターを省略すると、Pythonは自動的にそれを理解しようとします。

CPythonのソースコードを確認するとと、PySlice_GetIndicesEx()と呼ばれる関数が見つかります。この関数は、特定のパラメーターのスライスへのインデックスを計算します。Pythonでの論理的に同等のコードを次に示します。

この関数は、Pythonオブジェクトとスライスのオプションパラメータを取り、要求されたスライスの開始、停止、ステップ、およびスライスの長さを返します。

def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):

    length = len(obj)

    if step is None:
        step = 1
    if step == 0:
        raise Exception("Step cannot be zero.")

    if start is None:
        start = 0 if step > 0 else length - 1
    else:
        if start < 0:
            start += length
        if start < 0:
            start = 0 if step > 0 else -1
        if start >= length:
            start = length if step > 0 else length - 1

    if stop is None:
        stop = length if step > 0 else -1
    else:
        if stop < 0:
            stop += length
        if stop < 0:
            stop = 0 if step > 0 else -1
        if stop >= length:
            stop = length if step > 0 else length - 1

    if (step < 0 and stop >= start) or (step > 0 and start >= stop):
        slice_length = 0
    elif step < 0:
        slice_length = (stop - start + 1)/(step) + 1
    else:
        slice_length = (stop - start - 1)/(step) + 1

    return (start, stop, step, slice_length)

これはスライスの背後にあるインテリジェンスです。Pythonにはスライスと呼ばれる組み込み関数があるため、いくつかのパラメーターを渡して、欠落しているパラメーターを計算する方法を確認できます。

In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [22]: s = slice(None, None, None)

In [23]: s
Out[23]: slice(None, None, None)

In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)

In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]

In [26]: s = slice(None, None, -1)

In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]

In [28]: s = slice(None, 3, -1)

In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]

注:この投稿は、もともとは私のブログ、The Intelligence Behind Python Slicesで書かれていました。


29

原則として、ハードコードされた多くのインデックス値を使用してコードを記述すると、読みやすさとメンテナンスが混乱します。たとえば、1年後にコードに戻ると、コードを見て、それを書いたときに何を考えていたのか不思議に思うでしょう。示されている解決策は、コードが実際に何をしているのかをより明確に示す方法にすぎません。一般に、組み込みのslice()は、スライスが許可されている任意の場所で使用できるスライスオブジェクトを作成します。例えば:

>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]

スライスインスタンスsがある場合は、それぞれs.start、s.stop、およびs.step属性を調べることで、そのインスタンスに関する詳細情報を取得できます。例えば:

>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>

25

1.スライス表記

簡単にするために、スライスには1つの形式しかないことに注意してください。

s[start:end:step]

そして、これがどのように機能するかです:

  • s:スライスできるオブジェクト
  • start:反復を開始する最初のインデックス
  • end:最後のインデックス、インデックスは結果のスライスに含まれないことに注意してくださいend
  • stepstepインデックスごとに要素を選択

別の輸入の事:すべてはstartendstep省略することができます!それらが省略されている場合と、そのデフォルト値が使用されます:0len(s)1それに応じて。

可能なバリエーションは次のとおりです。

# Mostly used variations
s[start:end]
s[start:]
s[:end]

# Step-related variations
s[:end:step]
s[start::step]
s[::step]

# Make a copy
s[:]

注:(場合start >= endのみを考慮してstep>0)、Pythonは空のスライスを返します[]

2.落とし穴

上記の部分では、sliceがどのように機能するかに関するコア機能について説明し、ほとんどの場合に機能します。ただし、注意が必要な落とし穴がある可能性があるため、この部分ではそれらについて説明します。

負のインデックス

Python学習者を混乱させる最初のことは、インデックスが負になる可能性があるということです! パニックにならないでください:負のインデックスは逆数を意味します。

例えば:

s[-5:]    # Start at the 5th index from the end of array,
          # thus returning the last 5 elements.
s[:-5]    # Start at index 0, and end until the 5th index from end of array,
          # thus returning s[0:len(s)-5].

負のステップ

物事をより混乱させるのは、それもネガティブになる可能性があるというstepことです!

負のステップは、配列を逆方向に反復することを意味します:終了インデックスを含めて、終了インデックスを含め、開始インデックスを結果から除外します。

:ステップが負の場合、のデフォルト値はstartですlen(s)(が含まendれるため0、とs[::-1]は等しくありませんs[0])。例えば:

s[::-1]            # Reversed slice
s[len(s)::-1]      # The same as above, reversed slice
s[0:len(s):-1]     # Empty list

範囲外エラー?

驚いてください:インデックスが範囲外の場合、スライスはIndexErrorを発生させません!

インデックスが範囲外の場合、Pythonは状況に応じて、0またはlen(s)状況に応じてインデックスを設定するために最善を尽くします。例えば:

s[:len(s)+5]      # The same as s[:len(s)]
s[-len(s)-5::]    # The same as s[0:]
s[len(s)+5::-1]   # The same as s[len(s)::-1], and the same as s[::-1]

3.例

私たちが議論したすべてを説明して、例でこの答えを終えましょう:

# Create our array for demonstration
In [1]: s = [i for i in range(10)]

In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [3]: s[2:]   # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]

In [4]: s[:8]   # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]

In [5]: s[4:7]  # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]

In [6]: s[:-2]  # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]

In [7]: s[-2:]  # From second last index (negative index)
Out[7]: [8, 9]

In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]

In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]

In [12]: s[3:15]   # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]

In [14]: s[5:1]    # Start > end; return empty list
Out[14]: []

In [15]: s[11]     # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range

24

以前の回答では、有名なNumPyパッケージを使用して可能な多次元配列のスライスについては説明していません。

スライスは多次元配列にも適用できます。

# Here, a is a NumPy array

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
       [5, 7]])

:2コンマの前の " "は最初の次元に0:3:2作用し、コンマの後の" "は2番目の次元に作用します。


4
Pythonでこれを行うことはできず、Numpyでlistのみ行うことができるというフレンドリーな注意array
Mars Lee

15
#!/usr/bin/env python

def slicegraphical(s, lista):

    if len(s) > 9:
        print """Enter a string of maximum 9 characters,
    so the printig would looki nice"""
        return 0;
    # print " ",
    print '  '+'+---' * len(s) +'+'
    print ' ',
    for letter in s:
        print '| {}'.format(letter),
    print '|'
    print " ",; print '+---' * len(s) +'+'

    print " ",
    for letter in range(len(s) +1):
        print '{}  '.format(letter),
    print ""
    for letter in range(-1*(len(s)), 0):
        print ' {}'.format(letter),
    print ''
    print ''


    for triada in lista:
        if len(triada) == 3:
            if triada[0]==None and triada[1] == None and triada[2] == None:
                # 000
                print s+'[   :   :   ]' +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] == None and triada[2] != None:
                # 001
                print s+'[   :   :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] != None and triada[2] == None:
                # 010
                print s+'[   :{0:2d} :   ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] != None and triada[2] != None:
                # 011
                print s+'[   :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] == None and triada[2] == None:
                # 100
                print s+'[{0:2d} :   :   ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] == None and triada[2] != None:
                # 101
                print s+'[{0:2d} :   :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] != None and triada[2] == None:
                # 110
                print s+'[{0:2d} :{1:2d} :   ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] != None and triada[2] != None:
                # 111
                print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]

        elif len(triada) == 2:
            if triada[0] == None and triada[1] == None:
                # 00
                print s+'[   :   ]    ' + ' = ', s[triada[0]:triada[1]]
            elif triada[0] == None and triada[1] != None:
                # 01
                print s+'[   :{0:2d} ]    '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
            elif triada[0] != None and triada[1] == None:
                # 10
                print s+'[{0:2d} :   ]    '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
            elif triada[0] != None and triada[1] != None:
                # 11
                print s+'[{0:2d} :{1:2d} ]    '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]

        elif len(triada) == 1:
            print s+'[{0:2d} ]        '.format(triada[0]) + ' = ', s[triada[0]]


if __name__ == '__main__':
    # Change "s" to what ever string you like, make it 9 characters for
    # better representation.
    s = 'COMPUTERS'

    # add to this list different lists to experement with indexes
    # to represent ex. s[::], use s[None, None,None], otherwise you get an error
    # for s[2:] use s[2:None]

    lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]

    slicegraphical(s, lista)

このスクリプトを実行して試すことができます。以下は、スクリプトから取得したサンプルです。

  +---+---+---+---+---+---+---+---+---+
  | C | O | M | P | U | T | E | R | S |
  +---+---+---+---+---+---+---+---+---+
  0   1   2   3   4   5   6   7   8   9   
 -9  -8  -7  -6  -5  -4  -3  -2  -1 

COMPUTERS[ 4 : 7 ]     =  UTE
COMPUTERS[ 2 : 5 : 2 ] =  MU
COMPUTERS[-5 : 1 :-1 ] =  UPM
COMPUTERS[ 4 ]         =  U
COMPUTERS[-4 :-6 :-1 ] =  TU
COMPUTERS[ 2 :-3 : 1 ] =  MPUT
COMPUTERS[ 2 :-3 :-1 ] =  
COMPUTERS[   :   :-1 ] =  SRETUPMOC
COMPUTERS[-5 :   ]     =  UTERS
COMPUTERS[-5 : 0 :-1 ] =  UPMO
COMPUTERS[-5 :   :-1 ] =  UPMOC
COMPUTERS[-1 : 1 :-2 ] =  SEUM
[Finished in 0.9s]

負のステップを使用する場合、答えが右に1シフトすることに注意してください。


14

私の脳lst[start:end]start-番目の項目を含むことを喜んで受け入れているようです。それは「自然な仮定」だとさえ言うかもしれません。

しかし、時折疑念が忍び寄り、私の脳はend-th要素が含まれていないことを再確認するよう求めます。

これらの瞬間に私はこの単純な定理に依存しています:

for any n,    lst = lst[:n] + lst[n:]

このかわいらしいプロパティはlst[start:end]end-番目のアイテムが含まれているため、それが含まれていないことを示していますlst[end:]

この定理は、どの場合にも当てはまることに注意してくださいn。たとえば、あなたはそれを確認することができます

lst = range(10)
lst[:-42] + lst[-42:] == lst

を返しますTrue


12

私の意見では、Python文字列スライス表記法を次のように見ると(読み続けて)、理解し、よく覚えるでしょう。

次の文字列で作業してみましょう...

azString = "abcdefghijklmnopqrstuvwxyz"

知らない人のためにazString、表記法を使用して任意の部分文字列を作成できますazString[x:y]

他のプログラミング言語から来るとき、それは常識が損なわれるときです。xとyとは何ですか?

私は座って、xとyが何であるかを思い出し、最初の試行で文字列を適切にスライスするのに役立つ暗記テクニックを探すために、いくつかのシナリオを実行する必要がありました。

私の結論は、xとyは、追加したい文字列を囲む境界インデックスとして見られるべきだということです。したがって、表現を次のように、azString[index1, index2]またはさらに明確にする必要があります。azString[index_of_first_character, index_after_the_last_character]

これはその視覚化の例です...

Letters   a b c d e f g h i j ...
         ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
             ┊           ┊
Indexes  0 1 2 3 4 5 6 7 8 9 ...
             ┊           ┊
cdefgh    index1       index2

したがって、必要なのは、index1とindex2を目的のサブストリングを囲む値に設定することだけです。たとえば、部分文字列「cdefgh」を取得するには、次のように使用できますazString[2:8]、「c」の左側のインデックスは2で、「h」の右側のサイズは8である。

境界を設定していることを忘れないでください。そして、それらの境界は、このように部分文字列を囲むブラケットを配置できる位置です...

ab [ cdefgh ] ij

そのトリックは常に機能し、覚えやすいです。


11

以前の回答のほとんどは、スライス表記に関する質問を解決します。

スライスに使用される拡張インデックス構文はaList[start:stop:step]で、基本的な例は次のとおりです。

ここに画像の説明を入力してください

その他のスライスの例:15個の拡張スライス


10

Pythonでは、スライスの最も基本的な形式は次のとおりです。

l[start:end]

ここで、lはコレクション、start包含インデックス、およびend排他インデックスです。

In [1]: l = list(range(10))

In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]

In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]

最初からスライスする場合はゼロのインデックスを省略でき、最後までスライスする場合は冗長なので最終インデックスを省略できるため、冗長にしないでください。

In [5]: l[:3] == l[0:3]
Out[5]: True

In [6]: l[7:] == l[7:len(l)]
Out[6]: True

負の整数は、コレクションの終わりを基準にしてオフセットを行う場合に役立ちます。

In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]

In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]

以下のようなスライス時に範囲外のインデックスを提供することが可能です。

In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

コレクションをスライスすると、まったく新しいコレクションになることに注意してください。さらに、割り当てでスライス表記を使用する場合、スライス割り当ての長さは同じである必要はありません。割り当てられたスライスの前後の値が保持され、コレクションは新しい値を含むように縮小または拡大します。

In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]

In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]

In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]

In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]

開始インデックスと終了インデックスを省略すると、コレクションのコピーが作成されます。

In [14]: l_copy = l[:]

In [15]: l == l_copy and l is not l_copy
Out[15]: True

割り当て操作の実行時に開始インデックスと終了インデックスが省略されると、コレクションのコンテンツ全体が参照されているもののコピーで置き換えられます。

In [20]: l[:] = list('hello...')

In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

基本的なスライスに加えて、次の表記法を適用することも可能です。

l[start:end:step]

ここlで、はコレクション、startは包括的インデックス、endは排他的インデックスでありstep、のn番目ごとのアイテムを取得するために使用できるストライドですl

In [22]: l = list(range(10))

In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]

In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]

を使用stepすると、Pythonでコレクションを元に戻すための便利なトリックが提供されます。

In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

step次の例のように、負の整数を使用することもできます。

In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

ただし、負の値を使用するstepと、非常に混乱する可能性があります。また、であるためにはPython的には、使用しないでくださいstartendと、step単一のスライスインチ これが必要な場合は、これを2つの割り当てで行うことを検討してください(1つはスライスに、もう1つはストライドに)。

In [29]: l = l[::2] # This step is for striding

In [30]: l
Out[30]: [0, 2, 4, 6, 8]

In [31]: l = l[1:-1] # This step is for slicing

In [32]: l
Out[32]: [2, 4, 6]

10

Hello、World!を 1つ追加します。初心者向けのスライスの基本を説明する例。それは私を大いに助けました。

6つの値を持つリストを作ってみましょう['P', 'Y', 'T', 'H', 'O', 'N']

+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5

これで、そのリストの最も単純なスライスがそのサブリストになります。表記は[<index>:<index>]次のとおりです。重要なのは、次のようにそれを読み取ることです。

[ start cutting before this index : end cutting before this index ]

[2:5]上記のリストの一部を作成すると、次のようになります。

        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5

あなたは、カットをした前に、インデックスを持つ要素2と別のカットの前にインデックスを持つ要素5。したがって、結果はこれら2つのカットの間のスライス、リストになり['T', 'H', 'O']ます。


10

私はそれをforループのように個人的に考えています:

a[start:end:step]
# for(i = start; i < end; i += step)

また、startおよびの負の値endは、リストの最後を基準とし、上記の例ではによって計算されることに注意してくださいgiven_index + a.shape[0]


8

以下は文字列のインデックスの例です:

 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1

str="Name string"

スライスの例:[start:end:step]

str[start:end] # Items start through end-1
str[start:]    # Items start through the rest of the array
str[:end]      # Items from the beginning through end-1
str[:]         # A copy of the whole array

以下は使用例です。

print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti

5

スライスの負のインデックスが混乱していると感じる場合は、非常に簡単に考えることができますlen - index。負のインデックスをに置き換えます。たとえば、-3をに置き換えlen(list) - 3ます。

内部でスライスが何をするかを説明する最良の方法は、この操作を実装するコードでそれを示すことです。

def slice(list, start = None, end = None, step = 1):
  # Take care of missing start/end parameters
  start = 0 if start is None else start
  end = len(list) if end is None else end

  # Take care of negative start/end parameters
  start = len(list) + start if start < 0 else start
  end = len(list) + end if end < 0 else end

  # Now just execute a for-loop with start, end and step
  return [list[i] for i in range(start, end, step)]

4

基本的なスライス手法は、開始点、停止点、およびステップサイズ(ストライドとも呼ばれます)を定義することです。

最初に、スライスに使用する値のリストを作成します。

スライスする2つのリストを作成します。1つ目は、1から9までの数値リストです(リストA)。2番目も0〜9の数値リストです(リストB)。

A = list(range(1, 10, 1)) # Start, stop, and step
B = list(range(9))

print("This is List A:", A)
print("This is List B:", B)

Aの数字3とBの数字6にインデックスを付けます。

print(A[2])
print(B[6])

基本的なスライス

スライスに使用される拡張インデックス構文はaList [start:stop:step]です。開始引数とステップ引数は両方ともデフォルトでなしになっています-必要な引数は停止のみです。これは、範囲がリストAとBを定義するためにどのように使用されたかに似ていることに気づきましたか?これは、スライスオブジェクトがrange(start、stop、step)で指定されたインデックスのセットを表すためです。Python 3.4のドキュメント。

ご覧のとおり、stopだけを定義すると1つの要素が返されます。startのデフォルトはnoneなので、これは1つの要素のみを取得することになります。

最初の要素はインデックス0であり、インデックスです。このため、この演習では2つのリストを使用しています。リストAの要素は序数(最初の要素は1、2番目の要素は2など)に従って番号が付けられていますが、リストBの要素はそれらにインデックスを付けるために使用される番号です(最初の要素0は[0]、等。)。

拡張インデックス構文を使用して、値の範囲を取得します。たとえば、すべての値はコロンで取得されます。

A[:]

要素のサブセットを取得するには、開始位置と停止位置を定義する必要があります。

パターンaList [start:stop]を指定して、リストAから最初の2つの要素を取得します。


3

この提案はポジティブストライドには有効ですが、ネガティブストライドには適さないため、Pythonのチュートリアル図(他のさまざまな回答で引用)は適切ではないと思います。

これはダイアグラムです:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

図から、私はそうであると期待a[-4,-6,-1]していますyPが、そうですty

>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'

常に機能するのは、文字またはスロットを考慮し、インデックスをハーフオープンインターバルとして使用することです。正のストライドの場合は右オープン、負のストライドの場合は左オープンです。

このように、私はインターバル用語のa[-4:-6:-1]ようa(-6,-4]に考えることができます。

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5  
  -6  -5  -4  -3  -2  -1

 +---+---+---+---+---+---+---+---+---+---+---+---+
 | P | y | t | h | o | n | P | y | t | h | o | n |
 +---+---+---+---+---+---+---+---+---+---+---+---+
  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.