web-dev-qa-db-ja.com

Python list slice?

Python docは、リストをスライスすると新しいリストが返されると言っています。
「新しい」リストが返される場合、「スライスへの割り当て」に関連する次の疑問があります。

a = [1, 2, 3]
a[0:2] = [4, 5]
print a

これで、出力は次のようになります。

[4, 5, 3] 
  1. 何かを返している何かが表現の左側にどのように来ることができますか?
  2. はい、ドキュメントを読んで、リストをスライスすると「新しい」リストが返されるので、元のリストが変更されるのはなぜですか?その背後にあるメカニズムを理解することはできません。
78
Kartik Anand

非常によく似た構文を使用する2つの異なる操作を混同しています。

1)スライス:

b = a[0:2]

これにより、aのスライスのコピーが作成され、bに割り当てられます。

2)スライスの割り当て:

a[0:2] = b

このは、aのスライスをbの内容に置き換えます

構文は似ていますが(設計上想像してください!)、これらは2つの異なる操作です。

93
NPE

=演算子の左側にaを指定すると、Pythonの通常の割り当てが使用され、現在のコンテキストの名前aは、新しい値を指します。これは、aが指していた以前の値を変更しません。

a[0:2]演算子の左側に=を指定することで、Python使用したいスライスの割り当て。スライス割り当てはリストの特別な構文で、リストの内容を挿入、削除、または置換できます。

挿入

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

削除

>>> a
[-3, -2, -1, 0, 1, 2, 3]
>>> a[2:4] = []
>>> a
[-3, -2, 1, 2, 3]

交換

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

注意:

スライスの長さは、割り当てられたシーケンスの長さと異なる場合があり、ターゲットシーケンスで許可されている場合は、ターゲットシーケンスの長さが変更されます。 - source

スライスの割り当ては、 Tuple Unpacking と同様の機能を提供します。たとえば、a[0:1] = [4, 5]は次と同等です。

# Tuple Unpacking
a[0], a[1] = [4, 5]

Tuple Unpackingを使用すると、非順次リストを変更できます。

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

ただし、要素の挿入または削除はできないため、タプルのアンパックは置換に限定されます。

これらすべての操作の前後で、aはまったく同じリストです。 Pythonは、リストをインプレースで変更するための素敵な構文糖を提供するだけです。

52
Casey Kuball

以前に同じ質問に出くわしましたが、それは言語仕様に関連しています。 assignment-statements によると、

  1. 割り当ての左側がサブスクリプションの場合、Pythonはそのオブジェクトで __setitem__ を呼び出します。a[i] = xa.__setitem__(i, x)

  2. 割り当ての左側がスライスの場合、Pythonも__setitem__を呼び出しますが、異なる引数を使用します:a[1:4]=[1,2,3]a.__setitem__(slice(1,4,None), [1,2,3])と同等です

これが、「=」の左側のリストスライスの動作が異なる理由です。

18
Stan

割り当て操作の左側でスライスすることにより、割り当てるアイテムを指定します。

3
fraxel