2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Pythonのlist,numpyで、1次元,多次元で、代入,スライス,copy,deepcopyとかしてみた。一部np.shares_memoryで確認

Last updated at Posted at 2019-10-27

目的

いわゆる、shallow-copyとかdeep-copyに関するもの。
表題のことを30ケースほど試してみた。
結果は、以下に示すとおり(Python 3.7.2)。
比較的複雑なので、実現したい目的に応じて、その目的の観点にまとを絞って
方法を検討するのがいいと思いました。
(目的の例:計算時間都合?で、できるだけ、実際のCOPYを少なくしたい 等)
どういう動きになるのか、汎用的に頭に入れるのはやや困難?(ワタシのレベルでは)

結果に対するコメント

listとnumpyでは、違う。
1次元と2次元では、違う。
.deepcopy()は、わかり易いと感じた。
※np.shares_memoryは、期待の動きと違う。

「listとnumpyでは、違う。」の例

【A3】と【A13】の比較でわかるように、
listのスライスは、copyになっているが、
ndarrayのスライスは。参照になっている。
(どこかで、実行速度のため、コピーを避けている的な説明を見たことがあるが、それにしては、ndarrayもその他の条件であっさりコピーしていたり
するので、理由はよくわからない。)

>>> #【A3】1次元,list,スライス
...
>>> a = [1,2,3,4]
>>> b = a[:]
>>> a[0] = 900
>>> a[1] = 99911
>>> a
[900, 99911, 3, 4]
>>> b
[1, 2, 3, 4]
>>> #【A13】1次元,ndarray,スライス
...
>>> a = np.array([1,2,3,4])
>>> b = a[:]
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([  900, 99911,     3,     4])
>>> np.shares_memory(a,b)
True

上に示した【A3】と以下の【A4】をの比較すると、
違っている。
ここで、【A4】は、何もコピーされていないように見えるが、
topレベルはコピーされていることを
【A4_b】に示す。

 Python Pocket Referenceの説明がわかりやすい。
(出典:  Python Pocket Reference, 5th Edition
 Python In Your Pocket
 By Mark Lutz
 Publisher: O'Reilly Media)

L.copy()
Make a top-level(shallow)copy of L. ...

>>> #【A4】2次元,list,スライス
...
>>> a = [[1,2],[3,4]]
>>> b = a[:][:]
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
[[900, 2], [3, 99911]]
>>> b
[[900, 2], [3, 99911]]
>>>

>>> #【A4_b】2次元,list,スライス
...
>>> a = [[1,2],[3,4]]
>>> b = a[:][:]
>>> a[0] = [900,9000]#変更
>>>        #(topレベルは、コピーされていることを示すため)
... a[1][1] = 99911
>>> a
[[900, 9000], [3, 99911]]
>>> b
[[1, 2], [3, 99911]]
>>>

実行結果

>>> import numpy as np
>>> import copy
>>>
>>>

【A1】1次元,list,代入

>>> a = [1,2,3,4]
>>> b = a # 代入では
>>> a[0] = 900
>>> a[1] = 99911
>>> a # a が変われば
[900, 99911, 3, 4]
>>> b # b も変わる
[900, 99911, 3, 4]

【A2】2次元,list,代入

>>> a = [[1,2],[3,4]]
>>> b = a # 代入では
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a # a が変われば
[[900, 2], [3, 99911]]
>>> b # b も変わる
[[900, 2], [3, 99911]]

【A3】1次元,list,スライス

>>> a = [1,2,3,4]
>>> b = a[:] # 1次元スライスでの全代入は
>>> a[0] = 900
>>> a[1] = 99911
>>> a # a が変わっても
[900, 99911, 3, 4]
>>> b # b は変わらない
[1, 2, 3, 4]

【A4】2次元,list,スライス

>>> a = [[1,2],[3,4]]
>>> b = a[:][:]  # 2次元スライスでの全代入は
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a # a が変われば
[[900, 2], [3, 99911]]
>>> b # b も変わる
[[900, 2], [3, 99911]]

【A5】1次元,list,listのcopy関数

>>> a = [1,2,3,4]
>>> b = a.copy() # 1次元の.copy() では
>>> a[0] = 900
>>> a[1] = 99911
>>> a # a が変わっても
[900, 99911, 3, 4]
>>> b # b は変わらない
[1, 2, 3, 4]

【A6】2次元,list,listのcopy関数

>>> a = [[1,2],[3,4]]
>>> b = a.copy() # 2次元の.copy() では
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a # a が変われば
[[900, 2], [3, 99911]]
>>> b # b も変わる
[[900, 2], [3, 99911]]

【A7】1次元,list,copyモジュールのcopy関数

>>> a = [1,2,3,4]
>>> b = copy.copy(a) # copy.copy(1次元) では
>>> a[0] = 900
>>> a[1] = 99911
>>> a # a が変わっても
[900, 99911, 3, 4]
>>> b # b は変わらない
[1, 2, 3, 4]

【A8】2次元,list,copyモジュールのcopy関数

>>> a = [[1,2],[3,4]]
>>> b = copy.copy(a) # copy.copy(2次元) では
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a # a が変わると
[[900, 2], [3, 99911]]
>>> b # b も変わる
[[900, 2], [3, 99911]]

【A9】1次元,list,copyモジュールのdeepcopy関数

>>> a = [1,2,3,4]
>>> b = copy.deepcopy(a)
>>> a[0] = 900
>>> a[1] = 99911
>>> a
[900, 99911, 3, 4]
>>> b
[1, 2, 3, 4]

【A10】2次元,list,copyモジュールのdeepcopy関数

>>> a = [[1,2],[3,4]]
>>> b = copy.deepcopy(a)
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
[[900, 2], [3, 99911]]
>>> b
[[1, 2], [3, 4]]

【A11】1次元,ndarray,代入

>>> a = np.array([1,2,3,4])
>>> b = a
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([  900, 99911,     3,     4])
>>> np.shares_memory(a,b)
True

【A12】2次元,ndarray,代入

>>> a = np.array([[1,2],[3,4]])
>>> b = a
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
array([[  900,     2],
       [    3, 99911]])
>>> b
array([[  900,     2],
       [    3, 99911]])
>>> np.shares_memory(a,b)
True

【A13】1次元,ndarray,スライス

>>> a = np.array([1,2,3,4])
>>> b = a[:]
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([  900, 99911,     3,     4])
>>> np.shares_memory(a,b)
True

【A14】2次元,ndarray,スライス

>>> a = np.array([[1,2],[3,4]])
>>> b = a[:][:]
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
array([[  900,     2],
       [    3, 99911]])
>>> b
array([[  900,     2],
       [    3, 99911]])
>>> np.shares_memory(a,b)
True

【A15】1次元,ndarray,numpyのcopy関数

>>> a = np.array([1,2,3,4])
>>> b = a.copy()
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([1, 2, 3, 4])
>>> np.shares_memory(a,b)
False

【A16】2次元,ndarray,numpyのcopy関数

>>> a = np.array([[1,2],[3,4]])
>>> b = a.copy()
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
array([[  900,     2],
       [    3, 99911]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False

【A17】1次元,ndarray,copyモジュールのcopy関数

>>> a = np.array([1,2,3,4])
>>> b = copy.copy(a)
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([1, 2, 3, 4])
>>> np.shares_memory(a,b)
False

【A18】2次元,ndarray,copyモジュールのcopy関数

>>> a = np.array([[1,2],[3,4]])
>>> b = copy.copy(a)
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
array([[  900,     2],
       [    3, 99911]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False

【A19】1次元,ndarray,copyモジュールのdeepcopy関数

>>> a = np.array([1,2,3,4])
>>> b = copy.deepcopy(a)
>>> a[0] = 900
>>> a[1] = 99911
>>> a
array([  900, 99911,     3,     4])
>>> b
array([1, 2, 3, 4])
>>> np.shares_memory(a,b)
False

【A20】2次元,ndarray,copyモジュールのdeepcopy関数

>>> a = np.array([[1,2],[3,4]])
>>> b = copy.deepcopy(a)
>>> a[0][0] = 900
>>> a[1][1] = 99911
>>> a
array([[  900,     2],
       [    3, 99911]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False
>>> import numpy as np
>>> import copy

【B1】2次元,list,代入

>>> ee = [1,2]
>>> ff = [3,4]
>>> gg = [100,200]
>>>
>>> a = [ee,ff]
>>> b = a
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
[[1, 99911], [100, 200]]
>>> b
[[1, 99911], [100, 200]]

【B2】2次元,list,スライス

>>> ee = [1,2]
>>> ff = [3,4]
>>> gg = [100,200]
>>>
>>> a = [ee,ff]
>>> b = a[:][:]
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
[[1, 99911], [100, 200]]
>>> b
[[1, 99911], [3, 4]]

【B3】2次元,list,listのcopy関数

>>> ee = [1,2]
>>> ff = [3,4]
>>> gg = [100,200]
>>>
>>> a = [ee,ff]
>>> b = a.copy()
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
[[1, 99911], [100, 200]]
>>> b
[[1, 99911], [3, 4]]

【B4】2次元,list,copyモジュールのcopy関数

>>> ee = [1,2]
>>> ff = [3,4]
>>> gg = [100,200]
>>>
>>> a = [ee,ff]
>>> b = copy.copy(a)
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
[[1, 99911], [100, 200]]
>>> b
[[1, 99911], [3, 4]]

【B5】2次元,list,copyモジュールのdeepcopy関数

>>> ee = [1,2]
>>> ff = [3,4]
>>> gg = [100,200]
>>>
>>> a = [ee,ff]
>>> b = copy.deepcopy(a)
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
[[1, 99911], [100, 200]]
>>> b
[[1, 2], [3, 4]]

【B6】2次元,ndarray,代入

>>> ee = np.array([1,2])
>>> ff = np.array([3,4])
>>> gg = np.array([100,200])
>>>
>>> a = np.array([ee,ff])
>>> b = a
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
array([[  1,   2],
       [100, 200]])
>>> b
array([[  1,   2],
       [100, 200]])
>>> np.shares_memory(a,b)
True

【B7】2次元,ndarray,スライス

>>> ee = np.array([1,2])
>>> ff = np.array([3,4])
>>> gg = np.array([100,200])
>>>
>>> a = np.array([ee,ff])
>>> b = a[:]
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
array([[  1,   2],
       [100, 200]])
>>> b
array([[  1,   2],
       [100, 200]])
>>> np.shares_memory(a,b)
True

【B8】2次元,ndarray,numpyのcopy関数

>>> ee = np.array([1,2])
>>> ff = np.array([3,4])
>>> gg = np.array([100,200])
>>>
>>> a = np.array([ee,ff])
>>> b = a.copy()
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
array([[  1,   2],
       [100, 200]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False

【B9】2次元,ndarray,copyモジュールのcopy関数

>>> ee = np.array([1,2])
>>> ff = np.array([3,4])
>>> gg = np.array([100,200])
>>>
>>> a = np.array([ee,ff])
>>> b = copy.copy(a)
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
array([[  1,   2],
       [100, 200]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False

【B10】2次元,ndarray,copyモジュールのdeepcopy関数

>>> ee = np.array([1,2])
>>> ff = np.array([3,4])
>>> gg = np.array([100,200])
>>>
>>> a = np.array([ee,ff])
>>> b = copy.deepcopy(a)
>>> a[1] = gg
>>> ee[1] = 99911
>>> a
array([[  1,   2],
       [100, 200]])
>>> b
array([[1, 2],
       [3, 4]])
>>> np.shares_memory(a,b)
False

補足

>>>
>>>
>>>
>>> #【A4_b】2次元,list,スライス
...
>>> a = [[1,2],[3,4]]
>>> b = a[:][:]
>>> a[0] = [900,9000]#変更
>>>        #(topレベルは、コピーされていることを示すため)
... a[1][1] = 99911
>>> a
[[900, 9000], [3, 99911]]
>>> b
[[1, 2], [3, 99911]]
>>>

まとめ

コメントなどあれば、お願いします。

関連(本人)

pythonをストレスなく使う!(Python Pocket Reference (O'REILLY)が、分かり易いっ)

2
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?