파이썬 인자의 기본 값 할당

이태성·2022년 8월 27일

파이썬은 함수 혹은 클래스 초기화시 기본값을 넣어서 처리할 수 있다.
기본 값을 설정하면 값을 불필요하게 넣으려고 하지 않아도 되어 중복 코드를 줄일 수 있고 기능 확장시 새로운 인자가 생겨도 기존 작동에 오류를 피할 수 있다.

다만 인자의 기본 값을 사용할때 주의해야될 점이 있는데 바로 Mutable한 자료형을 사용하면 안된다는 점이다.

Mutable(뮤터블)한 자료형이란 바로 자료형에 담긴 내용물이 변할 수 있는 자료형이다. 파이썬 기준으로 하면 리스트와 딕셔너리와 같은 자료형이다.

예시를 들어보면

def add_arg_in_list(arg, box=[]):
    box.append(arg)
    return box

이런 코드가 존재한다고 가정할때

test_list = []
add_arg_in_list(1, test_list)
add_arg_in_list(1)
add_arg_in_list(2, test_list)
add_arg_in_list(3)

이런 식으로 값을 넣으면 어떻게 처리가 될까?

정답은

test_list = []
add_arg_in_list(1, test_list)
>>> [1]
add_arg_in_list(1)
>>> [1]
add_arg_in_list(2, test_list)
>>> [1, 2]
add_arg_in_list(3)
>>> [1, 3]
test_list
>>> [1, 2]

정답을 아는 사람도 있고 몰랐던 사람도 있을것이다.

여기서 이상한 점은

add_arg_in_list(3)
>>> [1, 3]

이 코드의 처리 결과물이다.

정답을 틀렸던 사람이라면 이런 결과를 예상했을 것이다.

add_arg_in_list(3)
>>> [3]

그럼 왜 이런 결과물이 나올까?

정답을 알기 위해선 파이썬이 기본값을 가진 인자를 어떻게 처리하는지 알아야한다.

우선 파이썬은 모든것이 object이다.

add_arg_in_list
>>> <function a at 0xffffb239cf70>
type(add_arg_in_list)
>>> <class 'function'>

함수 이름만 인터프리터에 넣어보면 이렇게 function이라는 이름의 클래스가 주소값과 함께나온다. 확실히 해보기 위해 type함수로 타입도 확인해보았다.

이제 우리가 함수로 선언하는 것들이 사실은 클래스로 생성한 인스턴스인걸 알았다.
그럼 함수라는 인스턴스 생성시 기본값이 있는 인자를 어떻게 처리하기에 이렇게 되는것일까?

파이썬은 함수를 생성하고 불러올시에 기본값이 정의된 인자를 매번 새롭게 할당하지 않는다. 대신 가지고 있다가 함수를 콜할때마다 가져와서 재사용하기 때문에 이런 결과가 나오게 된다.

그럼 왜 새롭게 할당하지 않을까? 바로 메모리 용량에 한계가 있기때문이다.
아마 하나의 함수를 만들고 함수를 백만번 호출한다고 할때 매번 재할당하면 오버플로우가 발생할것이다.

그래서 defaults라는 스페셜 메소드로 확인해보면

test_list = []
add_arg_in_list(1, test_list)
>>> [1]
add_arg_in_list(1)
>>> [1]
add_arg_in_list.__defaults__
>>> [1]
add_arg_in_list(2, test_list)
>>> [1, 2]
add_arg_in_list(3)
>>> [1, 3]
add_arg_in_list.__defaults__
>>> [1, 3]
test_list
>>> [1, 2]

이렇게 값이 남아있는걸 볼 수 있다.

이런 불상사?를 피하려면

def add_arg_in_list(arg, box=None):
	if box is None:
        box = []
        
    box.append(arg)
    return box

이렇게 인자에 기본값을 설정하는게 아닌 함수 내에 선언을하면 매 사용시 초기화된 값으로 처리가능하다.

마무리

이런 이유로 함수의 기본값이 있는 인자 할당시 Mutable한 자료형을 사용하면 함수를 불러올때마다 초기화되지 않고 재활용하기 때문에 이전 사용의 흔적이 남아있을 수 있어 주의해야한다.

물론 이런 특성을 활용해서 코드를 짜기도 하기때문에 무조권 나쁜것은 절때 아니다.

1개의 댓글

comment-user-thumbnail
2022년 9월 8일

저도 파이썬을 이용한 백엔드 개발을 하고 있어 얼마전에 공부한 개념이라 더욱 반갑내요!
저는 공부하면서 이런 간단해보이지만 작은 습관들이 중요한거 같다는 생각이 많이들었어요.
나중에 코드가 많아지고 복잡해지면 디버그할 때 어떤 원인인지 파악하기 힘들기에
function의 args에 immutable한 값을 넣어주어 scope를 제한해 관리를 한다는 것이 중요한거 같아요.
좋은 글 감사합니다!

답글 달기