[Python] For loop 안에서 List에 append를 했는데 이전 값이 유지되지 않고 새로운 값으로 덮어 씌워질 때
Python

[Python] For loop 안에서 List에 append를 했는데 이전 값이 유지되지 않고 새로운 값으로 덮어 씌워질 때

 

 

 

Python code를 짜고 있는데, 매우 이상한 현상을 발견했다.

(아마 나같은 Python 초심자 입장에서만 이상한 현상일지도 모름 ㅜㅜ)

Code는 아래와 같다.

 

A = np.zeros(2)
MyList = []

for i in range(3):
    for j in range(2):
        A[j] = np.random.normal(0, 1, 1)
    MyList.append(A)

 

위 코드에 대한 내 의도는 아래와 같다.

 

A라는 2-Element NumPy Array를 미리 선언하고,

Normal Distribution을 갖는 Random Number Aj번째 element로 저장한다.

이 상태에서 for loop이 2번 돌게 되면, 2개Random Number로 채워진 A를 얻는다.

이걸 미리 만들어둔 MyList에 append 하며, 밖에서 도는 for loop에 의해 3번 돌아간다.

 

결과적으로 나는 2-Element Random Number Array3개 있는 List를 원한 것이다.

그런데 code를 돌린 값을 보니 MyList 안에 있는 NumPy Array들이 모두 같은 값을 갖고 있었다.

 

>>MyList
[array([-0.31998222,  0.89518787]),
array([-0.31998222,  0.89518787]),
array([-0.31998222,  0.89518787])]

 

아니 이게 뭐야 왜 random number가 제대로 안 생겼지?

하고 문제 해결이 안 되어서 매우 고생했는데,

Python에서 variable 할당의 기초적인 개념이 모자라서 이런 실수를 저지른 것이었다.

MyListA라는 녀석을 append를 이용해 넣게 되면 A라는 값만 들어가는 것이 아니라,

A라는 variable 그 자체가 들어가도록 돌아가기 때문이다.

 

이 현상은 엑셀을 이용해 설명할 수도 있다.

 

이걸 원한게 아닌데.

 

위 사진과 같이, A1RAND()를 이용해 Random Number를 만들었다고 하더라도

MyListA1 자체를 3번 갖다붙여봤자 내가 의도한 3개의 Random Number가 생겨나지 않는다.

 

이걸 해결하려면 2가지 방법이 있다.

 

 

 


 

 

 

1. Copy

# Method 1
A = np.zeros(2)
MyList = []

for i in range(3):
    for j in range(2):
        A[j] = np.random.normal(0, 1, 1)
    MyList.append(A.copy())		# Use Copy Command

 

첫번째로, Copy가 하는 역할을 엑셀로 표현하자면 아래와 같다.

 

엑셀에서 붙여넣기 전 오른쪽 클릭을 한 상황.

 

엑셀에서 복사 & 붙여넣기를 할 때, 해당 셀 선택 후 오른쪽 버튼을 누르면 위와 같이 붙여넣기 옵션이 뜬다.

이 때, 123이라 적힌 2번째 옵션을 누르면 값만 붙여넣기를 할 수 있다.

 

현재 A1의 값과 다른 값이 D1으로 복사된다.

 

이런 과정이 for loop으로 3번 일어나면, 아래와 같은 결과가 나온다.

 

3개의 Random Number를 얻었다.

 

 

 


 

 

 

2. Reinitialize

# Method 2
MyList = []

for i in range(3):
	A = np.zeros(2)				# Reinitialize
    for j in range(2):
        A[j] = np.random.normal(0, 1, 1)
    MyList.append(A)

 

사실 이러한 현상이 나타난 근본적인 원인은 A라는 변수를 for loop을 이용해 update할 때,

A를 다시 define하는 방식이 아니라 Aindex에 접근해 element를 바꿔주는 방식으로 진행했기 때문에 생겼다.

따라서, for loop 내에서 A가 아예 새로 define이 되도록 바꿔주면 해결할 수 있는 문제다.

 

>>MyList
[array([ 0.60393122, -2.58748742]), 
array([0.6296992 , 0.79161653]), 
array([ 0.47488607, -0.15437113])]

 

위 두가지 방법 중 어느 하나를 선택해서 진행해도 결과가 잘 나온다.