확인한 환경과 범위

Windows · Python 3.12.4. 본문의 첫 예제를 실행하여 표준 출력과 예상 결과가 일치함을 확인했습니다. 연습문제의 모든 입력을 검증한 것은 아닙니다.

이 글의 순서 3개 단락

함수의 매개변수에 items=[]를 지정하면 호출할 때마다 빈 리스트가 만들어질 것처럼 보입니다. 하지만 기본값을 생략한 호출은 함수가 정의될 때 만들어진 같은 리스트를 사용합니다.

아래 전체 예제를 Python 3에서 실행해 보세요. 첫 부분은 기본값이 평가되는 시점을 표시하고, 이어서 None을 사용하는 방법과 직접 전달한 리스트의 변경을 비교합니다.

Python 함수의 기본 리스트가 호출할 때마다 누적되는 이유 — 첫 예제의 실제 실행 결과

기본 리스트는 언제 만들어질까?

예제의 make_default()는 빈 리스트를 만들면서 기본값 생성을 출력합니다. 이 함수는 add_shared를 호출할 때가 아니라 def add_shared 문이 실행될 때 호출됩니다. 따라서 첫 번째 호출보다 기본값 생성이 먼저 표시될 것으로 예상할 수 있습니다.

첫 번째 호출은 기본 리스트에 1을 추가하므로 [1]을 출력합니다. 두 번째 호출도 인자를 생략해 같은 리스트를 사용하므로 2를 추가한 뒤 [1, 2]를 출력합니다. append()는 리스트를 제자리에서 변경합니다.

기본값을 만드는 식은 함수 정의가 실행될 때마다 평가됩니다. 예를 들어 같은 def 문을 다시 실행해 함수를 새로 정의하면 새 기본값도 만들어집니다. 매 호출마다 만들어지는 것은 아닙니다. Python 공식 FAQ: 기본값이 공유되는 이유

호출마다 새 리스트가 필요하다면

add_fresh는 기본값으로 None을 사용합니다. items is None일 때 함수 안에서 []를 만들기 때문에 인자를 생략한 두 호출은 각각 별도의 리스트에 값을 추가합니다. 예상 결과는 [1], [2]입니다.

if not items 대신 if items is None을 사용한 점도 중요합니다. 빈 리스트 []를 직접 전달한 경우에도 그 리스트를 그대로 사용하기 때문입니다.

직접 전달한 리스트와 복사

add_fresh(3, original)은 전달받은 original에 직접 3을 추가합니다. None을 기본값으로 바꾸어도 명시적으로 전달한 리스트의 변경까지 막아 주지는 않습니다. 호출자가 전달한 리스트에 값을 누적하는 것이 목적이라면 이 동작을 그대로 사용할 수 있습니다.

반대로 원본 리스트를 보존해야 한다면 add_copy처럼 전달받은 리스트를 list(items)로 복사한 뒤 변경하세요. 예제에서 original은 [3]으로 남고, 반환된 copied는 [3, 4]가 됩니다. 이 복사는 얕은 복사이므로 중첩 리스트의 내부 객체까지 독립적으로 변경해야 한다면 별도의 깊은 복사가 필요할 수 있습니다.

표시된 출력은 예제 코드에서 예상되는 결과입니다.

함께 찾아볼 코드 사전

CHECK THE SOURCE

참고한 공식 문서

기능 설명은 위 문서를 참고했으며, 예제의 입력·결과와 한계는 본문에 따로 기록했습니다.

한 줄씩 이해하고, 차곡차곡 기록합니다.이 글의 오류 제보하기 ↗