Python 은 왜 가 변 대상 을 기본 매개 변수 값 으로 사용 할 수 없 습 니까?

먼저 문 제 를 보 겠 습 니 다.

>>> def func(numbers=[], num=1):
... numbers.append(num)
... return numbers
>>> func()
[1]
>>> func()
[1, 1]
>>> func()
[1, 1, 1]
우 리 는 버그 를 발견 한 것 같 습 니 다.함수 func()를 같은 방식 으로 호출 할 때마다 결과 가 다 르 고 돌아 오 는 목록 이 계속 길 어 지고 있 습 니 다.

>>> id(func())
4330472840
>>> id(func())
4330472840
위 에서 알 수 있 듯 이 함수 의 반환 값 은 같은 목록 대상 입 니 다.그들의 id 값 은 같 기 때문에 목록 의 요소 가 변화 하고 있 을 뿐 입 니 다.왜 이러 지?
이것 은 함수 의 특성 으로 볼 때 Python 에서 함 수 는 첫 번 째 대상(function is the first class object)입 니 다.다시 말 하면 함수 도 대상 입 니 다.정수,문자열 과 마찬가지 로 변수 에 값 을 부여 하고 매개 변수 로 전달 할 수 있 으 며 반환 값 으로 도 사용 할 수 있 습 니 다.함수 도 함수 의 이름,함수 의 기본 매개 변수 목록 과 같은 속성 이 있 습 니 다.

#      
>>> func.__name__ 
'func'
#          
>>> func.__defaults__ 
([1, 1, 1, 1, 1], 1)
def 는 실행 가능 한 구문 입 니 다.Python 해석 기 가 def 문 구 를 실행 할 때 메모리 에 함수 대상 을 만 듭 니 다.함수 대상 은 하나 뿐 입 니 다.functionobject 입 니 다.여러 번 호출 되 었 다 고 여러 함수 대상 이 나타 나 지 않 습 니 다.

함수 대상 이 생 성 되면 속성:이름과 기본 매개 변수 목록 이 초기 화 됩 니 다.

초기 화 완료 시 속성default__ 첫 번 째 기본 매개 변수 numbers 는 빈 목록 을 가리 키 고 있 습 니 다.
함수 가 처음 호출 되 었 을 때 func()를 처음 실 행 했 을 때 함수 에 있 는 논리 코드 를 실행 하기 시 작 했 습 니 다.코드 논 리 는 numbers 에 값 이 1 인 요 소 를 추가 하 는 것 입 니 다.

두 번 째 func()를 호출 하여 numbers 에 요 소 를 계속 추가 합 니 다.

세 번 째,네 번 째 는 이에 따라 유추 한다.
그래서 지금 너 는 왜 같은 함 수 를 호출 하 는 지 알 아야 한다.반환 값 은 확실히 매번 다르다.같은 목록(numbers)대상 을 공유 하기 때문에 호출 할 때마다 이 목록 에 요 소 를 추가 합 니 다.
만약 우리 가 numbers 인 자 를 표시 하고 지정 한다 면 결 과 는 전혀 다 릅 니 다.

>>> func(numbers=[10, 11])
[10, 11, 1]

numbers 가 다시 할당 되 었 기 때문에 초기 화 된 목록 을 가리 키 지 않 고 우리 가 전달 한 새 목록 대상 을 가리 키 기 때문에 반환 값 은[10,11,1]이 되 었 습 니 다.
그렇다면 우 리 는 어떻게 앞의 그런 상황 을 피해 야 합 니까?가 변 대상 을 매개 변수 로 하지 않 는 기본 값 입 니 다.
올 바른 방식:

>>> def func(numbers=None, num=1):
... if numbers is None:
... numbers = [num]
... else:
... numbers.append(num)
... return numbers
...
>>> func()
[1]
>>> func()
[1]
>>> func()
[1]
호출 할 때 지정 한 인자 가 없 으 면 호출 방법 을 사용 할 때 기본 매개 변수 numbers 는 매번 다시 할당 되 기 때문에 호출 할 때마다 numbers 는 새로운 대상 을 가리 키 게 됩 니 다.이것 이 바로 전자 와 의 차이 점 이다.
그렇다면 우 리 는 가 변 대상 을 매개 변수 로 하 는 기본 값 으로 영원히 사용 해 서 는 안 된다 는 것 일 까?파 이 썬 이 이런 문법 을 가지 고 있 는 이상 반드시 그의 응용 장면 이 있 을 것 이다.마치 for..else 문법 과 같다.우 리 는 가 변 대상 으로 캐 시 기능 을 할 수 있다.
예 를 들 어 하나의 수의 단 계 를 계산 할 때 가 변 대상 의 사전 을 캐 시 값 으로 하여 캐 시 를 실현 할 수 있 습 니 다.캐 시 에 계 산 된 값 을 저장 하고 두 번 째 호출 할 때 중복 계산 없 이 캐 시 에서 가 져 옵 니 다.

def factorial(num, cache={}):
if num == 0:
return 1
if num not in cache:
print('xxx')
cache[num] = factorial(num - 1) * num
return cache[num]
print(factorial(4))
print("-------")
print(factorial(4))
출력:

---     ---
xxx
xxx
xxx
xxx
24
---     ---
24
두 번 째 호출 할 때 cache 에서 직접 값 을 가 져 왔 습 니 다.그래서 가 변 대상 을 기본 값 으로 하 는 것 이 Python 의 결함 이 라 고 하 셨 습 니까?아니 야,그렇지!너 는 여전히 하나의 특성 으로 사용 하 는 것 이 좋 겠 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기