본문 바로가기
Python/Python FAQ

Python 어떻게 할당 후 예기치 않게 변경되지 않도록 목록을 복제할 수 있나요?, How do I clone a list so that it doesn't change unexpectedly after assignment?

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

질문


new_list = my_list를 사용하는 동안, new_list에 대한 모든 수정 사항은 매번 my_list를 변경합니다. 이유는 무엇이며, 이를 방지하기 위해 리스트를 복제하거나 복사하는 방법은 무엇인가요?


답변


new_list = my_list는 실제로 두 번째 목록을 만들지 않습니다. 할당은 목록의 참조만 복사하기 때문에 할당 후에 new_listmy_list는 동일한 목록을 참조합니다.

실제로 목록을 복사하려면 여러 가지 옵션이 있습니다:

  • 내장된 list.copy() 메서드를 사용할 수 있습니다 (Python 3.3 이후 사용 가능):

    new_list = old_list.copy()
    
  • 슬라이스를 사용할 수 있습니다:

    new_list = old_list[:]
    

    알렉스 마르텔리의 의견 (최소한 2007년 당시)에 따르면, 이것은 이상한 구문이며 언제나 사용하는 것이 의미가 없습니다. ;) (그의 의견으로는 다음 것이 더 가독성이 좋습니다).

  • 내장된 list() 생성자를 사용할 수 있습니다:

    new_list = list(old_list)
    
  • 일반적인 copy.copy()를 사용할 수 있습니다:

    import copy
    new_list = copy.copy(old_list)
    

    이것은 old_list의 데이터 유형을 먼저 찾아야 하기 때문에 list()보다 약간 느립니다.

  • 목록의 요소를 복사해야 하는 경우 일반적인 copy.deepcopy()를 사용하세요:

    import copy
    new_list = copy.deepcopy(old_list)
    

    이것은 가장 느리고 가장 많은 메모리를 사용하는 방법입니다. 하지만 때로는 피할 수 없습니다. 이것은 재귀적으로 작동하며, 중첩된 목록 (또는 다른 컨테이너)의 모든 수준을 처리할 수 있습니다.

예제:

import copy

class Foo(object):
    def __init__(self, val):
         self.val = val

    def __repr__(self):
        return f'Foo({self.val!r})'

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# 원본 목록 및 인스턴스 편집
a.append('baz')
foo.val = 5

print(f'original: {a}\nlist.copy(): {b}\nslice: {c}\nlist(): {d}\ncopy: {e}\ndeepcopy: {f}')

결과:

original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]
반응형

댓글