2010-06-17 9 views
27

Numpy와 Python 2.6.5에서 이상한 문제가 있습니다. 난 numpy 배열을 할당 한 다음 새 변수를 그 변수와 동일시합니다. 새 배열에 대한 연산을 수행하면 원본 값도 변경됩니다. 왜 그런가요? 아래 예를 참조하십시오. Python을 처음 접했고 프로그래밍 전반에 대해 친절하게 가르쳐주었습니다.numpy 배열 할당 문제

-Sujan

실제로는 전혀 문제가되지 않습니다
>>> import numpy as np 
>>> a = np.array([[1,2],[3,4]]) 
>>> b = a 
>>> b 
array([[1, 2], 
     [3, 4]]) 
>>> c = a 
>>> c 
array([[1, 2], 
     [3, 4]]) 
>>> c[:,1] = c[:,1] + 5 
>>> c 

array([[1, 7], 
     [3, 9]]) 
>>> b 
array([[1, 7], 
     [3, 9]]) 
>>> a 
array([[1, 7], 
     [3, 9]]) 

답변

56

; 배열 (및 다른 객체)이 파이썬에서 작동하는 방식입니다.

이렇게 생각하십시오. 코드 예제에서 만든 배열은 메모리의 특정 위치에있는 개체입니다. 하지만 파이썬이 메모리를 어디에서 찾아야할지 알려줌으로써 프로그램에서 사용할 수 없습니다. 당신은 그것에게 이름을 주어야합니다. 당신이

a = np.array([[1,2],[3,4]]) 

를 쓸 때 당신은 모두 배열을 생성하고 그것을 참조하는 이름, a을 만들 수 있습니다. 이 시점부터 파이썬은 a이 "메모리 주소 0x123674283"(또는 무엇이든)을 가리킨다는 것을 알고 있습니다. 파이썬은 위의 코드를 실행 한 후 할당 할 때,이 테이블

..., 
'a' : 0x123674283, 
... 

포함됩니다, 그래서 모든 정보를 포함 (내 기억이 맞다 경우 "심볼 테이블"이라고 함) 파이썬 런타임의 내부 테이블이있다 그것은 큰 배열 인 것 때문에

b = a 

파이썬 같은 다른 하나 개의 변수의 값은 시간이 오래 걸릴 것입니다, 전체 배열을 복사하지 않습니다. 대신 심볼 테이블로 이동하여 의 메모리 주소를 b의 테이블에있는 새 행에 복사합니다. 당신은

..., 
'a' : 0x123674283, 
..., 
'b' : 0x123674283, 
... 

그래서 당신이 볼, ab 실제로 즉 동일한 개체 메모리에 동일한 위치에 참조하고 함께 바람 그래서. 하나의 변경 사항은 동일한 항목에 대한 두 개의 이름이기 때문에 다른 변경 사항에 반영됩니다.

실제로 배열 복사본을 만들려면 명시 적으로 배열을 호출해야합니다. Numpy 배열에는 copy 메서드가 있습니다.이 메서드는이 용도로만 사용할 수 있습니다. 그래서 당신은 작성하는 경우

b = a.copy() 

다음 파이썬 먼저 실제로 배열의 카피 할 것 - 즉, 그것의 주소 0x123904381에서 말을하자, 옆으로 메모리의 새로운 영역을 설정하고 메모리 주소 0x123674283 모든 사본로 이동을 메모리의 후자의 섹션으로부터 이전의 배열의 값 그래서 당신은 똑같은 내용이 기억 속에있는 두 개의 다른 장소에 앉아 있습니다. 당신이 b의 요소 중 하나를 변경하면 ab가 더 이상 컴퓨터 메모리의 동일한 부분을 참조하지 않기 때문에 지금

..., 
'a' : 0x123674283, 
..., 
'b' : 0x123904381, 
... 

, 그 변화는 a에 표시되지 않습니다. 배열 데이터는 두 개의 독립적 인 사본이므로 다른 하나에 영향을 미치지 않고 하나를 변경할 수 있습니다.

+6

훌륭한 설명을 보내 주셔서 감사합니다. 말할 필요도없이 문제가 해결되었지만, 시간을내어 상황을 설명해 주셔서 감사합니다. 너는 나를 계몽했다! – Sujan

+1

"파이썬은 배열 전체를 복사하지 않기 때문에 시간이 오래 걸립니다." - 걸릴 시간이 적다는 것과, 이런 방식으로 구현하지 않으면 별도의 포인터 유형과 같은 것을 도입해야하며, 복잡하게 만드는 것이 필요하다는 것입니다. – user2357112

1

간단히 말해서, 변수 할당은 기존 개체에 대한 새로운 참조를 만듭니다.

A = object # A points to object in memory 
    B = A  # B points to the same object