본문으로 건너뛰기
개발 머꼬
개발 노트Python
hohyeon.dev16

Python 함수 기본 인자에 리스트를 썼다가 데이터가 계속 쌓인 이유

  • #Common Pitfall
  • #Engineering Note
  • #Python

문제 발생

기본 인자를 빈 리스트로 준 함수를 여러 번 호출했더니, 이전 호출에서 추가한 값이 다음 호출에도 남아있는 버그가 발생했습니다.

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

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b'] -- 기대와 다름, 새 리스트가 아님

원인 분석

Python은 함수의 기본 인자값을 함수가 정의되는 시점에 딱 한 번만 평가합니다. 매 호출마다 새로 만드는 것이 아닙니다. items=[][]는 함수가 정의될 때 생성된 하나의 리스트 객체이고, 이 객체가 모든 호출에서 공유됩니다. 리스트, 딕셔너리, 셋처럼 가변(mutable) 객체를 기본값으로 쓰면 한 호출에서 수정한 내용이 다음 호출에도 그대로 남습니다.

반대로 정수, 문자열, 튜플처럼 불변(immutable) 객체를 기본값으로 쓰면 애초에 내부에서 수정할 방법이 없으므로 이 문제가 발생하지 않습니다.

해결 방안

기본값을 None으로 주고, 함수 본문에서 실제 기본값을 새로 만듭니다.

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

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['b'] -- 매번 새 리스트

이 패턴은 딕셔너리, 셋 등 다른 가변 기본값에도 동일하게 적용합니다. 반대로 이 동작을 의도적으로 활용하는 경우도 있습니다 — 함수 호출 사이에 상태를 캐싱하고 싶을 때 가변 기본 인자를 캐시 저장소로 쓰는 기법인데, 의도가 명확히 드러나도록 주석을 남기지 않으면 다음에 코드를 보는 사람이 버그로 오해하기 쉽습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.