복붙노트

[PYTHON] 파이썬 목록 혼란

PYTHON

파이썬 목록 혼란

다음 코드가 있다고 가정 해 보겠습니다.

a_list = [[0]*10]*10

다음 목록이 생성됩니다.

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

그런 다음 첫 번째 요소의 첫 번째 요소를 수정하려고합니다.

a_list[0][0] = 23

목록의 첫 번째 요소 만 수정 될 것으로 예상했지만 실제로는 각 목록의 첫 번째 요소가 변경되었습니다.

[[23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

이 문제를 피하기 위해 내 데이터를 나타내는 또 다른 방법을 찾을 수 있었지만 왜 이런 일이 발생 했습니까? 첫 번째 목록이 변경된 이유는 무엇입니까? 두 번째 * 10을 할 때 파이썬은 실제로 새로운 메모리 블록을 할당하는 대신 첫 번째리스트의 주소를 복사합니까?

해결법

  1. ==============================

    1.주소 복사에 대한 직감이 정확합니다. 다음과 같이 생각하십시오.

    주소 복사에 대한 직감이 정확합니다. 다음과 같이 생각하십시오.

    sub_list = [0] * 10
    a_list = [sub_list] * 10
    

    이 코드는 실제로 위에 게시 한 코드와 같습니다. 즉, a_list의 요소를 변경할 때마다 동일한 목록 sub_list를 실제로 변경하고 있다는 것입니다. 다음을 입력하여 확인할 수도 있습니다.

    a_list = [[0] * 10] * 10
    for n in a_list:
        print id(n)
    

    그리고 그것은 모든 요소에 대해 동일하게 나타날 것입니다. 이 문제를 해결하려면 다음을 사용해야합니다.

    a_list = [[0] * 10 for _ in range(10)]
    

    a_list의 모든 요소에 대해 새 하위 목록을 작성합니다.

  2. ==============================

    2.목록에는 객체에 대한 참조가 포함됩니다. 목록의 곱셈은 참조를 반복합니다 (동일한 객체로!). 정수와 같이 변경 불가능한 객체의 경우에는 문제가 없지만 동일한 목록에 대한 여러 참조가 있습니다.

    목록에는 객체에 대한 참조가 포함됩니다. 목록의 곱셈은 참조를 반복합니다 (동일한 객체로!). 정수와 같이 변경 불가능한 객체의 경우에는 문제가 없지만 동일한 목록에 대한 여러 참조가 있습니다.

    이 패턴 [_ 0 xrange (10)에 대한 [0] * 10]을 사용하여 별도의 목록을 만듭니다.

  3. ==============================

    3.그 이유는 간단합니다. 실제로 의심되는 것처럼 10 개가 아니라 1 개의 목록 만 있습니다.

    그 이유는 간단합니다. 실제로 의심되는 것처럼 10 개가 아니라 1 개의 목록 만 있습니다.

    In [1]: [[0]*10]*10
    Out[1]:
    [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
    
    In [2]: map(id, _)
    Out[2]:
    [54094624,
     54094624,
     54094624,
     54094624,
     54094624,
     54094624,
     54094624,
     54094624,
     54094624,
     54094624]
    

    10 개의 목록을 만들려면 다음과 같은 식을 사용하여 쉽게 만들 수 있습니다.

    [[0]*10 for x in xrange(10)]
    
  4. from https://stackoverflow.com/questions/5957341/python-list-confusion by cc-by-sa and MIT license