Python에서 함수의 매개변수는 기본값을 가질 수 있습니다. 이 기본값은 함수가 정의될 때 실행되는 표현식입니다(즉, 단 한번). 함수가 호출될 때마다 동일한 기본값이 사용되므로 수정하면 이후의 모든 호출에 영향을 미칩니다. 이것은 매우 혼란스러운 버그를 만들 수 있습니다. 변경 가능한 기본값을 다른 객체에 저장하는것도 좋지 않습니다(예: 속성으로). 그러면 여러 인스턴스가 동일한 값을 공유하고 하나의 개체를 수정하면 모든 객체가 수정됩니다.
이 규칙은 다음과 같은 경우에 문제를 야기합니다.
- 기본값은 함수에서 수정되거나 변수 이외에 할당되며 다음 유형 중 하나를 가집니다:
- 내장 함수: set, dict, list
- collections 모듈: deque, UserList, ChainMap, Counter, OrderedDict, defaultdict, UserDict
- 또는 기본값의 속성이 할당된 경우.
규칙을 어긴 코드
다음 예제에서 매개 변수 “param”은 list()를 기본값으로 사용합니다. 이 list는 한 번만 생성된 다음 모든 호출에서 다시 사용됩니다. 따라서 이 list에 ‘a’를 추가하면 다음 호출은 [‘a’]를 기본값으로 갖게 됩니다.
def myfunction(param=list()): # 규칙을 어긴 코드.
param.append('a') # 기본값 수정.
return param
print(myfunction()) # returns ['a']
print(myfunction()) # returns ['a', 'a']
print(myfunction()) # returns ['a', 'a', 'a']
다음 예제에서는 MyClass.param의 여러 인스턴스에 동일한 list를 사용합니다.
class MyClass:
def __init__(self, param=list()): # 규칙을 어긴 코드.
self.param = param # MyClass의 모든 인스턴스에 동일한 list가 사용됩니다
def process(self, value):
self.param.append(value) # 동일한 리스트 수정
a1, a2 = (MyClass(), MyClass())
a1.process("value")
print(a1.param) # ['value']
print(a2.param) # ['value']
규칙을 준수한 해결책
def myfunction(param=None):
if param is None:
param = list()
param.append('a')
return param
print(myfunction()) # returns ['a']
print(myfunction()) # returns ['a']
print(myfunction()) # returns ['a']
class MyClass:
def __init__(self, param=None):
if param is None:
self.param = list()
else:
self.param = param
def process(self, value):
self.param.append(value)
a1, a2 = (MyClass(), MyClass())
a1.process("value")
print(a1.param) # ['value']
print(a2.param) # []
예외
매우 드문 경우지만 기본값을 수정하는 것은 괜찮습니다. 예를 들어, 기본값을 캐시로 사용할 수 있습니다. 매개 변수 이름에 “cache” 또는 “memo”가 포함된 경우 문제가 발생하지 않습니다(메모할 때와 같이)
같이보면 좋은 자료
If you like SONARKUBE, don’t forget to give me a star. ![]()