2016-05-31 3 views
0

다음 최소 예제를 고려하십시오. 다양한 중첩 깊이의 목록 요소를 복사 할 때 누군가가 명백하게 일치하지 않는 논리 인 numpy을 설명 할 수 있습니까?numpy 배열을 복사 할 때 명백하게 일치하지 않는 동작

import numpy as np 

L = [[[[1, 1], 2, 3]]] 
A1 = np.array(L) 

A2 = A1.copy() 

A1[0][0][2] = 'xx' 
A1[0][0][0][0] = 'yy' 

print "\nA1 after changes:\n{}".format(A1) 
print "\nA2 only partially changed:\n{}".format(A2) 

결과 : 다음

A1 after changes: 
[[[['yy', 1] 2 'xx']]] 

A2 only partially changed: 
[[[['yy', 1] 2 3]]] 

는 :

>>> print A1[0][0][2] == A2[0][0][2] 
False 
>>> print A1[0][0][0][0] == A2[0][0][0][0] 
True 

나는 힘든 시간 3가 교체되지 않는 이유 자신에게 설명을 가지고 있지만 더 깊은 수준에서 1입니다.

  1. A2 = np.array(A, copy=True)A2 = np.empty_like(A); np.copyto(A4, A)

  2. A2 = A[:] 상기 코드와 동일하게 동작은 A2 = A와 동일하게 동작 : 양쪽이 동일한 변화

  3. import copy; A2 = copy.deepcopy(A)는 I 독립을 만들 수있는 유일한 솔루션 인 후 부.

+0

깊은 사본으로 만 이러한 현상이 일어나지 않는다는 것을 알았 으면 무엇이 당신을 혼란 스 킵니까? 다른 경우에는 * 동일한 참조 가능한 객체에 대한 참조를 복사합니다. – jonrsharpe

+1

'dtype = object' 배열을 가지고 있기 때문입니다 ... 기본적으로 파이썬리스트와 2 개의 파이썬 정수에 대한 참조를 보유하고있는 배열을 가지고 있습니다. 배열을 복사하면 참조가 복사됩니다. – mgilson

+0

나는 그 복제본을 좋아하지 않는다. 탁구장 배열에는 특별한 복사 문제가 있습니다. 그리고'dtype' 객체 배열은이 문제를 더욱 복잡하게 만듭니다. 이 질문은 다시 열어야합니다. – hpaulj

답변

1

배열에서 봐, 먼저 그 구조를 이해 :

In [139]: A1 
Out[139]: array([[[[1, 1], 2, 3]]], dtype=object) 

In [140]: A1.shape 
Out[140]: (1, 1, 3) 

는 그것은 dtype=object 배열이다; 즉 요소는 숫자가 아니라 객체 포인터입니다. 또한 3 차원 요소로 3 차원입니다.

In [142]: A1[0,0] 
Out[142]: array([[1, 1], 2, 3], dtype=object) 

는 배열이므로 A1[0,0]A1[0][0]보다 낫다. 기능적으로 동일하지만 더 명확합니다. A1[0,0,:]이 더 좋습니다. 어쨌든,이 수준에서 우리는 모양이 (3,) 인 배열을 가지고 있습니다. 즉 3d 요소를 가진 1d입니다.

In [143]: A1[0,0,0] 
Out[143]: [1, 1] 

In [144]: A1[0,0,2] 
Out[144]: 3 

이제는 목록과 숫자, 즉 A1의 개별 요소를 얻습니다. 목록은 변경 가능하며 숫자는 변경할 수 없습니다.

우리는 문자열로 3 요소 (숫자)를 변경할 수 있습니다 :

In [148]: A1[0,0,2]='xy' 

이 첫번째 요소 목록의 요소를 변경하려면, 내가 혼합 색인을 사용할 필요가 아닌 4 수준의 배열 색인 생성.

In [149]: A1[0,0,0,0] 
... 
IndexError: too many indices for array 

In [150]: A1[0,0,0][0]='yy' 

In [151]: A1 
Out[151]: array([[[['yy', 1], 2, 'xy']]], dtype=object) 

A1은 여전히 ​​3d 개체 배열입니다. 우리는 몇 가지 요소를 변경했습니다. 'xy'변경은 'yy'변경과 다릅니다. 하나는 배열을 변경하고, 다른 하나는 배열의 목록 요소입니다.

A2=A1.copy()은 요소 배열 (데이터 버퍼)이 A1 인 새로운 배열을 만듭니다. 따라서 A2에는 A1과 동일한 객체에 대한 포인터가 있습니다.

'xy'는 A1에 포인터를 변경했지만 A2 복사본은 변경하지 않았습니다.

'yy'변경으로 인해 A1이 가리키는 목록이 수정되었습니다. A2에는 동일한 목록에 대한 포인터가 있으므로 변경 내용이 표시됩니다.

In [152]: L 
Out[152]: [[[['yy', 1], 2, 3]]] 

A3 = A[:]viewA1의 생산 :

L 것으로, 원래의 중첩 된 목록이 같은 변화를 본다. A3A1과 동일한 데이터 버퍼를 가지므로 모든 변경 사항을 볼 수 있습니다.

A4 = A도 변경되지만, A4은보기 또는 사본이 아닌 A1에 대한 새로운 참조입니다.

이전에 제기 된 duplicate answer은 목록의 참조, 복사본 및 전체 복사본을 처리했습니다. 이것은 L이 목록이고 A1이 여러 가지 방법으로 목록 주위의 배열 래퍼 인 객체 배열이므로 여기에서 관련이 있습니다. 그러나 A1도 numpy 배열이며 viewcopy 사이의 구분이 추가되었습니다.

이 배열은 numpy 배열을 사용하지 않으며 dtype 버전의 개체조차 사용하지 않습니다. 그것은 유익한 예이지만 실용적이지 못합니다. 배열에 deepcopy을 수행해야하는 경우 배열을 잘못 사용했을 가능성이 큽니다.