私はこの構文がどのように動作するのか知っていますが、私はPythonがどのように置き換えられて左側のリストを変更するのかを知りたいと思います。 Ex。PythonはどのようにLHS上のスライスと修正をリストしますか?
L = [0, 1, 2, 3, 4]
L[0:2] = [5]
print L #L is now [5, 2, 3, 4]
これはどのようにして行われますか?
私はこの構文がどのように動作するのか知っていますが、私はPythonがどのように置き換えられて左側のリストを変更するのかを知りたいと思います。 Ex。PythonはどのようにLHS上のスライスと修正をリストしますか?
L = [0, 1, 2, 3, 4]
L[0:2] = [5]
print L #L is now [5, 2, 3, 4]
これはどのようにして行われますか?
あなたの質問にタグが付いているpython 2.7では、__setslice__
のマジックメソッドです。詳細はhere in the datamodel sectionと記載されています。
__setslice__(self, i, j, sequence)
Called to implement assignment to self[i:j].
これは下位互換性のための古いインターフェイスです。たとえば、L[0:2:]
(これに相当するはずです)のスライスに割り当てる場合は、実際には__setitem__
という新しいインターフェイスを使用します。
フードの下に行くか見て、あなたが独自のクラスを作成し、リストを継承することができます。
>>> class MyList(list):
... def __setslice__(self, *args):
... print '__setslice__ called with args:', args
... list.__setslice__(self, *args)
... def __setitem__(self, *args):
... print '__setitem__ called with args:', args
... list.__setitem__(self, *args)
...
はのは、いくつかの例を見てみましょう:渡さ
>>> L = MyList([0, 1, 2, 3, 4])
>>> L[0:2] = [5]
__setslice__ called with args: (0, 2, [5])
3つの引数があります常に左と右のエンドポイント、次に割り当ての右側のオブジェクトを選択します。常に__setitem__
の新しいインタフェースを介して移動し、sliceオブジェクトのインスタンスを渡すのではなく/ストップインデックスを開始するステップとスライスを使用
>>> L[0:2:] = [5]
__setitem__ called with args: (slice(0, 2, None), [5])
。エンドポイントを省略
>>> L[1:] = [5]
__setslice__ called with args: (1, 9223372036854775807, [5])
はsys.maxint
使用(開始を省略すると、使用0)。
>>> L[::] = 'potato'
__setitem__ called with args: (slice(None, None, None), 'potato')
右側のオブジェクトはリストである必要はありません。
私が言及したい最後のことは、組み込みのリストタイプから派生している場合は__setslice__
で悩むだけです。通常あなたはではありません新しいコードを書く場合、近代的な方法はabstract base classを継承することになります。具体的にはcollections.Sequence
はリストのような構造のための明白な選択です。そうすれば、ビルトインリストが下位互換性のために持っているすべてのいぼやハックを心配する必要はありません。
これは__setitem__
または__setslice__
の方法で達成されます。 (__setslice__
は、IIRCではなく、python3.xでは削除されています)。リストについて
、表現:
L[start: stop] = some_iterable
は(非包括的)some_iterable
からアイテムを取ると、停止するように最初からインデックスにある要素を置き換えます。だから、あなたのデモコードでは、あなたが持っている:
L[0:2] = [5]
これは、インデックス0
と1
の要素を取り、5
に置き換えます。
置き換えリストは、置き換えられるサブリストと同じ長さである必要はありません。
おそらくそれを考えるには良い方法は、次の操作を行うためのインプレース方法として、次のとおりです。
L[a:b] = c
# equivalent to the following operation (done in place)
L[:a] + list(c) + L[b:]
あなたが実際にそれが起こるか好奇心であれば、ソースコードは最高です参照。 PyList_SetSliceはlist_ass_sliceを呼び出し、右側の反復可能性をシーケンス(tuple
またはlist
IIRC)に変えます。適切な量のデータを保持するように配列のサイズを変更し、スライスの右側にあるものを適切な場所にコピーし、新しいデータをコピーします。リストが拡大するか縮小するかによって、いくつかの異なるコードパス(および操作の順序)がありますが、それはその基本的な要点です。
ありがとうございました! – SpegooterCode