함수 매개변수의 기본값을 수정하거나 할당하면 안됩니다.

 

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. :star2:

원문으로 바로가기

Star This Project