[Python] 깊은 복사 / 얕은 복사

이정연·2023년 4월 26일
0

얕은 복사

깊은 복사가 무엇이고 얕은 복사가 무엇인지 개념부터 살펴보자.

우리가 파이썬에서 리스트를 다른 변수에 할당하는 경우를 살펴보자

예를 들면 이런 경우

origin = [0,1,2,3]
cpy = origin
print(cpy)

[0,1,2,3]

겉으로 보기에는 origin과 cpy가 별개의 리스트인것 같지만 엄연히 말하면 서로 같은 리스트다.

위 그림과 같이 origin과 cpy는 [0,1,2,3]이라는 동일한 주소를 가리키고 있는 것 뿐이다.

따라서 한 쪽의 리스트에 변경 사항이 발생하면 다른 한 쪽도 영향을 받는다.

예를 들어,

cpy.pop()
print(origin)

[0,1,2]

cpy에서 pop() 연산을 수행했음에도 origin의 원소도 빠진다.

위 그림으로 다시 설명하면 아래와 같은 상황인 것이다.

깊은 복사

그렇다면 깊은 복사가 무엇인지 대략 예상이 갈 것이다.

이처럼 별도의 주소값을 갖는 리스트를 따로 만드는 것이다.

따라서 cpy에서 pop()을 해도 origin에 영향을 미치지 않는다.

python에서 얕은 복사를 default로 설정해놓은 이유는 아마도 메모리를 조금 더 효율적으로 관리하기 위함이 아닐까 추측해본다.

방법 1 : copy package

python에서는 내장 패키지로 deep copy 모듈을 지원해준다.

사용 방법은 아래와 같다.

import copy
origin = [0,1,2,3]
cpy = copy.copy(origin)

cpy.pop()
print(origin)
print(cpy)

[0,1,2,3]

[0,1,2]

방법 2 : list create

리스트를 처음부터 다시 만드는 방법도 있다. 아래처럼.

origin = [0,1,2,3]
cpy = [x for x in origin]

cpy.pop()
print(origin)
print(cpy)

함수 인자에도 적용이 될까?

다음과 같은 코드의 실행 결과가 어떻게 될까?

def foo(lst):
    lst.pop()
    return lst

if __name__ == '__main__':
    origin = [0,1,2,3]

    print(foo(origin))
    print(origin)

1️⃣ [0,1,2] / [0,1,2,3]
2️⃣ [0,1,2] / [0,1,2]

정답은 2번이다.

이것 때문에 틀렸던 프로그래머스 문제가 괄호 회전하기

함수의 파라미터로 리스트를 전달해도 얕은 복사 특성 때문에 local이 아닌 global로 적용된다.

따라서, 함수 내부에서만 쓰이는 local 변수로 활용하려면 깊은 복사를 해야 한다.

출처

https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy/

profile
0x68656C6C6F21

0개의 댓글