[python] default parameter 사용 시 주의할 점

윤상원·2021년 11월 29일
0

python

목록 보기
1/1

인자의 기본값이 함수 사이에서 공유되는 상황

def foo(mylist = []):
    mylist.append(1)
    return mylist

print(foo())
print(foo())
print(foo())
  • 함수 foo는 인자의 기본값으로 빈 리스트를 갖고, 함수 내부에서 빈 리스트에 1을 추가해서 리턴한다.

  • 우리의 의도대로라면, print(foo())를 실행할 때마다 실행 결과는 [1]로 같아야 한다.

  • 그러나, 실제 실행 결과를 보면 아래와 같다.

[1]
[1,1]
[1,1,1]
  • 위와 같은 결과가 나오는 이유가 무엇일까?

파이썬에서는 모든 것이 객체이다.

  • 파이썬에서는 모든것들(숫자, 문자, 함수 등)을 객체로 취급한다.

  • 따라서 파이썬에서의 함수는 하나의 객체이다.

  • foo의 매개변수 mylist는 객체 foo의 속성으로 존재한다.

  • 즉, foo를 call할 때마다 새로운 mylist를 만들어 주는것이 아니라, mylistfoo 객체 안에 만들어 두고, 공유하는 것이다.

  • 이것은 인자의 기본값을 mutable한 객체(list, dictionary, class 등)로 정의할 때 의도하지 않은 동작을 발생시킬 수 있다.

  • immutable한 객체(Number, String, Tuple, None 등)의 경우, 객체 안의 속성으로 공유하더라도, 값이 변하지 않기 때문에 아래와 같이 우리의 의도대로 함수가 동작한다.

def bar(mynumber=3):
    mynumber += 1
    return mynumber
    
print(bar())
print(bar())
print(bar())

#결과
4
4
4
  • 그러나, mutable한 객체의 경우 객체 안의 속성으로 공유하는 과정에서 값이 변하기 때문에 foo함수와 같은 결과가 나타난다.

해결 방법

이를 해결하기 위해 파이썬 공식 문서에서는 아래와 같은 방법을 사용하도록 권고하고 있다.

def foo(mylist=None):
    if mylist is None:
        mylist = []
    mylist.append(1)
    return mylist
        
print(foo())
print(foo())
print(foo())

#결과
[1]
[1]
[1]

위와 같이 작성하면 foo함수가 기본값으로 실행될 때마다 mylist가 매번 초기화되기 때문에 함수 사이에서 mylist가 공유되지 않는다.

참고자료

파이썬 공식 문서 : Why are default values shared between objects?

0개의 댓글