ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION1169 / 1500
언어·런타임난이도 하5분 답변 목표 · 보강본

Python 함수의 기본 인자를 빈 리스트로 뒀는데 이전 호출에서 추가한 값이 다음 호출에도 남습니다. 기본값 객체는 언제 만들어지며 어떻게 고치나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

함수의 기본 인자는 함수가 호출될 때마다 만드는 값이 아니라 함수 정의를 평가할 때 한 번 만들어집니다. 따라서 기본값으로 리스트나 딕셔너리 같은 mutable 객체를 두고 함수 안에서 수정하면, 그 객체가 다음 호출에도 그대로 남습니다. 이는 일반적인 메모리 누수라기보다 함수 호출 사이의 상태 공유를 의도하지 않게 만든 버그입니다.

정의 때 만들어지는 기본값

def add_item(item, bucket=[]):
    bucket.append(item)
    return bucket

print(add_item("a"))
print(add_item("b"))

출력은 ['a'] 다음 ['a', 'b']입니다. 두 호출이 서로 다른 빈 리스트를 받은 것이 아니라 같은 기본 리스트를 사용했기 때문입니다. 기본값으로 None을 두고, 인자가 생략된 호출마다 본문에서 새 리스트를 만들면 의도하지 않은 가변 상태 공유를 피할 수 있습니다. 불변 기본값도 재사용될 수 있지만 그 객체 자체를 변경하는 문제가 없다는 차이가 있습니다.

def add_item(item, bucket=None):
    if bucket is None:
        bucket = []
    bucket.append(item)
    return bucket

print(add_item("a"))
print(add_item("b"))

의도적 상태와 API 계약

이 경우 출력은 각각 ['a'], ['b']입니다. 단, 호출자가 같은 리스트를 명시적으로 넘겨 여러 호출에서 누적하려는 API라면 공유가 의도일 수 있으므로 그 계약을 문서화하겠습니다. 기본 인자에서 []를 피하는 것만으로 모든 공유 상태가 사라지는 것은 아니며, 함수 본문이 전역·캐시·클래스 속성을 수정하는지도 함께 확인해야 합니다.

선택 기준과 검증

None sentinel도 유효한 입력 값이어야 한다면 생략을 표현하는 별도 객체가 필요합니다. 기본 리스트를 캐시로 의도적으로 재사용할 수는 있지만 동시 호출, 무효화, 상한, 테스트 격리를 함께 설계해야 합니다. 기본값을 고친 뒤에도 전역·클래스 속성·클로저가 상태를 공유하는지 확인해 문제를 함수 정의 한 줄로 축소하지 않겠습니다.

기본값으로 datetime.now()나 함수를 호출한 결과를 두어도 같은 평가 시점 문제가 생깁니다. 요청마다 현재 시각을 기대했는데 모듈 로드 당시 값이 계속 사용될 수 있습니다. 함수 정의 때 계산할 상수인지 호출 때 계산할 값인지를 구분하고, 호출별 값은 본문에서 만들거나 factory를 받겠습니다. 이는 mutable 여부와 별개인 기본값 평가 시점의 규칙입니다.

빈 리스트를 if not bucket으로 바꾸는 수정은 호출자가 명시적으로 넘긴 빈 리스트까지 새 객체로 대체할 수 있습니다. 생략만 처리하려면 is None이나 전용 sentinel을 사용해야 합니다. 기본값을 통해 의도적으로 상태를 저장하는 코드는 테스트 순서와 동시 요청에 의존할 수 있으므로, 캐시라면 명시적인 소유 객체로 옮겨 수명·상한·무효화를 드러내는 편이 유지보수에 좋습니다. 정의를 두 번 평가하면 서로 다른 기본 객체가 생긴다는 점도 같은 함수 객체의 반복 호출과 구분하겠습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • 기본값 정의 시 평가 시점을 설명한다.
  • None sentinel과 명시적 객체 공유를 구분한다.
  • 의도한 캐시의 동시성·무효화 비용을 판단한다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • 기본 인자가 호출 때마다 새 mutable 객체가 된다고 말한다.
  • None을 리스트처럼 append할 수 있다고 설명한다.
  • 이 현상을 모든 메모리 증가의 원인인 누수로만 부른다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기