파이썬의 비밀스러운 삶: Default 함정

발행: (2026년 2월 27일 오후 02:37 GMT+9)
3 분 소요
원문: Dev.to

Source: Dev.to

왜 빈 리스트를 기본 인수로 절대 사용하면 안 되는지.

🎧 오디오 버전: 듣는 걸 선호하시나요? 이 심층 탐구의 AI 팟캐스트 확장 버전을 YouTube에서 확인하세요.

📺 비디오 버전: 보는 걸 선호하시나요? 7분짜리 시각적 설명을 YouTube에서 확인하세요.

공유 메모리

def add_student(name, student_list=[]):
    student_list.append(name)
    return student_list

# First call
print(add_student("Alex"))

# Second call
print(add_student("Alice"))

두 번째 호출이 ['Alex', 'Alice']를 반환하는 이유는 기본 리스트가 함수가 정의될 때 한 번만 생성되고, 호출될 때마다 새로 만들어지지 않기 때문입니다.

“좀비” 변수 보기

__defaults__ 속성을 통해 저장된 기본값을 확인할 수 있습니다:

print(f"Before: {add_student.__defaults__}")
add_student("Alex")
print(f"After:  {add_student.__defaults__}")

출력

Before: ([],)
After:  (['Alex'],)

리스트가 함수 객체에 붙어 있어 호출 사이에 지속됩니다. 이 동작은 mutable(변경 가능한) 기본값(예: 리스트, 딕셔너리)에서만 발생합니다. None, 문자열, 정수와 같은 immutable(변경 불가능) 기본값은 변경될 수 없으므로 안전합니다.

전문가 표준

권장되는 패턴은 None을 sentinel 값으로 사용하고 함수 내부에서 새 리스트를 만드는 것입니다:

def add_student(name, student_list=None):
    if student_list is None:
        student_list = []
    student_list.append(name)
    return student_list

이제 명시적인 리스트가 제공되지 않을 때마다 매 호출마다 새로운 리스트가 생성됩니다.

Margaret’s Cheat Sheet: 기본 인수

  • 안전한 기본값: None, True, False, 0, "" (불변 객체)
  • 위험한 기본값: [], {}, set() (가변 객체)

문제점: 기본 인수는 정의 시점에 한 번 평가됩니다.

해결책: 기본값으로 None을 사용하고 함수 본문 안에서 가변 객체를 초기화합니다.

디버거: my_function.__defaults__를 검사하여 숨겨진 공유 상태를 감지합니다.

0 조회
Back to Blog

관련 글

더 보기 »

그룹별 배열 뒤집기

문제 설명: 주어진 크기 k의 그룹으로 배열을 뒤집는다. 배열은 길이 k인 연속적인 청크(윈도우)로 나뉘며, 각 청크는 뒤집힌다.