7

これは、Pythonがデータと変数をどのように処理するかについての簡単な質問です。私は多くの実験を行い、Pythonをほとんど理解させましたが、これが私をつまずかせ続けることを除いて:

[編集:わかりやすくするために例を分離して再配置しました]

例1:

>>> a = [[1], 2]
>>> a[0:1]
[[1]]
>>> a[0:1] = [[5]]
>>> a
[[5], 2] # The assignment worked.

例2:

>>> a = [[1], 2]
>>> a[0:1][0]
[1]
>>> a[0:1][0] = [5]
>>> a
[[1], 2] # No change?

例3:

>>> a = [[1], 2]
>>> a[0:1][0][0]
1
>>> a[0:1][0][0] = 5
>>> a
[[5], 2] # Why now?

誰かがここで何が起こっているのか私に説明できますか?

a[0:1]これまでのところ、回答は、の最初の要素への参照を含む新しいリストを返すと主張しているようですa。しかし、それが例1をどのように説明しているかわかりません。

4

3 に答える 3

7

a [0:1]は、配列[1]への参照を含む新しい配列を返しているため、参照呼び出しを介して内部配列を変更することになります。

最初のケースで[1]配列が変更されない理由は、コピーされた外部配列に新しい内部配列値を割り当てているためです。

結論-a[0:1]はデータのコピーを返しますが、内部データはコピーされません。

于 2010-10-29T20:13:44.097 に答える
3

私の理解では、スライスすると新しいオブジェクトが返されます。つまり、戻り値は新しいリストです。

したがって、代入演算子を使用して元のリストの値を変更することはできません

>>> a = [[1], 2, 3]
>>> k = a[0:2]
>>> id(a)
4299352904
>>> id(k)
4299353552
>>> 

>>> id(a)
4299352904
>>> id(a[0:2])
4299352832

線に沿っていくつかのより多くの演劇

>>> k = 5
>>> 
>>> id(k)
4298182344
>>> a[0] = [1,2]
>>> a
[[1, 2], 2, 3]
>>> id(a)
4299352904
>>> 

[編集:質問の2番目の部分]

>>> a[0:1] = [[5]]

次の表記は、一般にスライス割り当てとも呼ばれます 。組み込みリストの動作はアトミック(削除+挿入)であり、一度に実行されます。私の理解では、これはカスタムシーケンスでは許可されていません。

于 2010-10-29T20:15:18.477 に答える
1

インデックスを使用した3つの異なる操作があり、すべてメソッド呼び出しに変換されます。

  • a[i] = b=>a.__setitem__(i, b)
  • del a[i]=>a.__delitem__(i)
  • a[i]式として使用=>a.__getitem__(i)

ここaで、、は式でありb、コロンの短縮構文を使用して作成されたスライスオブジェクトを含めることができます。例えば:ii

>>> class C(object):
...     def __setitem__(self, *a):
...             print a
... 
>>> C()[1] = 0
(1, 0)
>>> C()['foo'] = 0
('foo', 0)
>>> C()['foo':'bar'] = 0
(slice('foo', 'bar', None), 0)
>>> C()['foo':'bar',5] = 0
((slice('foo', 'bar', None), 5), 0)

したがって、3番目の例で起こっていることは次のとおりです。

a[0:1][0][0] = 5

になります

a.__getitem__(slice(0,1)).__getitem__(0).__setitem__(0, 5)

1つ目__getitem__はリストの一部のコピーを返しますが、2つ目__getitem__はその中の実際のリストを返し、それを使用して変更し__setitem__ます。

一方、2番目の例は次のようになります

a.__getitem__(slice(0,1)).__setitem__(0, 5)

したがって__setitem__、元のリストをそのままにして、スライスされたコピーで呼び出されます。

于 2010-10-29T21:56:06.097 に答える