특정 행을 왼쪽 또는 오른쪽으로 x만큼 회전시키는 문제를 풀던 중
for문이 돌면서 리스트가 자꾸 동기화되길래 왜인지 원인을 찾다가리스트 참조문제임을 알고 새롭게 알게된 내용을 정리하기 위해 작성합니다.
특정 행을 왼쪽 또는 오른쪽으로 x만큼 회전시키는 문제
이차원 배열이 주어지고, 회전 명령의 갯수인 m
m개의 회전명령 정보(행 순서, 0은 왼쪽으로, 1은 오른쪽으로, x만큼 회전)
5
10 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19
3
2 0 3
5 1 2
3 1 4
row, dir, col으로 변수를 지정한 후,
new_list라는 새로운 리스트를 만듦
거기에 특정 행이 회전 한 후의 결과값을 저장
new_list를 arr의 특정행에 넣어줌
n = int(input())
arr = [list(map(int, input().split())) for _ in range(n)]
m = int(input())
# 1. 회전시키기
# new_list = [i for i in range(n)]
for _ in range(m):
row, dir, count = map(int, input().split())
row -= 1
new_list = [i for i in range(n)]
for i in range(n):
if dir == 0: # 왼쪽
new_idx = i - count
if new_idx < 0: # 음수라면 +n만큼
new_idx += n
new_list[new_idx] = arr[row][i] # 인덱스 재배치
else: # 오른쪽
new_idx = i + count
if new_idx >= n:
new_idx -= n
new_list[new_idx] = arr[row][i]
arr[row] = new_list
회차를 돌 때, 분명 new_list는 내가 원하는 대로 값이 나왔지만
i == 1일때 순서가 끝나면 1번째의 new_list가 첫번째의 arr[row]에도 영향을 미쳐서 값이 동기화되는 현상 발생!!
10 13 10 12 15
25 50 53 15 11
25 50 53 15 11
19 27 29 37 27
25 50 53 15 11
이렇게 i가 2일때, new_list의 결과가 1행, 4행, 2행에도 영향을 미친것을 볼 수 있다.
내가 for문 안에서 new_list를 선언(초기화) 한 것이 아니라 for문 밖에서 선언을 하고 for문 안에서는 하지않았는데, 이로인해 arr[1], arr[4], arr[2]가 모두
같은 리스트인 new_list를 참조하고 있던 것이였다.
나는 new_list의 원소값이 바뀌므로 굳이 초기화를 하지않아도 독립적일 것이라고 생각하였는데 리스트는 참조로 동작하기 때문에 같은 주소를 참조하고 있던 것이었다.
예를 들어 다음과 같은 코드를 살펴보자.
이 코드는 내가 위에서 작성했던 코드와 똑같이 작동한다.
list의 인덱스로 원소값만을 바꾸고 그 list를 arr1에 넣는 형태
arr1 = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
list1 = [0, 1, 2, 3, 4]
for a in range(3):
for i in range(5):
list1[i] = [i+100]
arr1[a] = list1
print(arr1)

파이썬 튜터 페이지를 이용해 시각화한 것인데, 보는 것과 같이 arr1[0], arr1[1], arr[2]가 같은 주소를 참조하는 것을 볼 수 있다.
그래서 list의 원소값이 바뀔때마다 arr도 바뀌었던 것..!
나는 각 행에 new_list를 넣을 때, 독립적이길 원하기 때문에 new_list[:]를 사용해서 new_list의 값을 복사하여 새로운 리스트를 생성하거나
arr[row] = new_list[:]
for문 안에서 순회를 돌 때마다 new_list를 초기화 (새로운 주소 생성) 해주는 방법이 있다.
list는 참조로 동작하기 때문에, 초기화(새로운 주소 생성)을 하지않고 같은 주소를 계속 참조하게 된다면 다음 동작에도 계속해서 영향을 미칠 수 있다!!
파이썬튜터 : https://pythontutor.com/
(시각적으로 나와있어 이해가 잘된다 ㅎㅎ)