본문 바로가기
Python/Python FAQ

Python 하위 목록 전체에 영향을 미치는 목록의 변경사항이 예기치 않게 반영됩니다., List of lists changes reflected across sublists unexpectedly

by 베타코드 2023. 6. 9.
반응형

질문


나는 리스트의 리스트를 만들었다:

>>> xs = [[1] * 4] * 3
>>> print(xs)
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]

그리고 나서, 내부 값 중 하나를 변경했다:

>>> xs[0][0] = 5
>>> print(xs)
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]

왜 각 하위 리스트의 첫 번째 요소가 5로 변경되었을까?


또한 참조:


답변


[x]*3을 작성하면 사실상 [x, x, x] 리스트를 얻습니다. 즉, 같은 x에 대한 3개의 참조가있는 목록입니다. 그런 다음이 단일 x를 수정하면 모든 세 참조를 통해 볼 수 있습니다 :

x = [1] * 4
xs = [x] * 3
print(f"id(x): {id(x)}")
# id(x): 140560897920048
print(
    f"id(xs[0]): {id(xs[0])}\n"
    f"id(xs[1]): {id(xs[1])}\n"
    f"id(xs[2]): {id(xs[2])}"
)
# id(xs[0]): 140560897920048
# id(xs[1]): 140560897920048
# id(xs[2]): 140560897920048

x[0] = 42
print(f"x: {x}")
# x: [42, 1, 1, 1]
print(f"xs: {xs}")
# xs: [[42, 1, 1, 1], [42, 1, 1, 1], [42, 1, 1, 1]]

이를 수정하려면 각 위치에서 새 목록을 만드는지 확인해야합니다. 하나의 방법은 다음과 같습니다.

[[1]*4 for _ in range(3)]

이렇게하면 3 회마다 [1]*4을 다시 평가하고 1 개의 목록을 3 개의 참조가 아닌 각 위치에서 새로 만듭니다.


리스트 내포가 수행되는 동안 요소 표현식을 매번 다시 평가합니다. [[1] * 4 for n in range(3)][x**2 for x in range(3)]x**2을 매번 다시 평가하는 이유와 동일한 이유로 매번 [1] * 4을 다시 평가합니다. [1] * 4의 모든 평가는 새로운 목록을 생성하므로 리스트 내포는 원하는 대로 작동합니다.

그와 별개로, [1] * 4[1]의 요소를 복사하지 않지만, 이는 무관합니다. 정수는 변경 불가능하기 때문에 1.value = 2와 같은 작업을 수행하여 1을 2로 바꿀 수 없습니다.

반응형

댓글