Python 함수 매개변수의 기본값이 변경 가능한 객체인 경우 주의해야 합니다.

WBOY
풀어 주다: 2023-04-22 13:37:07
앞으로
1224명이 탐색했습니다.

피보나치 함수의 재귀 속도를 높이기 위해 변수 개체가 Python 함수 매개 변수의 기본값으로 전달되는 것을 봤습니다. 코드는 다음과 같습니다.

def fib(n, cache={0: 0, 1: 1}):
if n not in cache:
cache[n] = fib(n - 1) + fib(n - 2)
return cache[n]
로그인 후 복사

매우 참신하지 않습니까, 실제로도 가능합니다. 이렇게 하면 속도가 정말 매우 빠릅니다. 실행 결과는 다음과 같습니다.

小心此坑:Python 函数参数的默认值是可变对象

그러나 저는 이렇게 하지 말 것을 권하며, IDE에서도 그렇게 하면 좋지 않다는 메시지를 표시합니다.

小心此坑:Python 函数参数的默认值是可变对象

모든 것이 객체이고, Python 함수도 객체이고, 매개변수가 객체의 속성이기 때문입니다. 매개변수의 기본값은 컴파일 단계에서 이미 함수에 바인딩되어 있습니다. 변수 개체인 경우 Python 함수 매개 변수의 기본값은 모든 호출자에 의해 저장되고 공유됩니다. 즉, 함수의 기본 매개 변수 값이 List 또는 Dict와 같은 변수 개체이고 호출자 A가 수정하는 경우 그러면 호출자 B는 호출 시 A의 수정된 결과를 보게 됩니다. 이러한 패턴은 종종 위의 fib 알고리즘과 같이 예상치 못한 결과를 생성하지만 이는 버그에 가깝습니다.

다음 간단한 코드를 살펴보세요.

def func(n, li = []):
for i in range(n):
li.append(i)
print(l)

func(2) # [0,1]
func(3,l=[1,2]) # [1,2,0,1,2]
func(2) # [0,1]
로그인 후 복사

먼저 이 코드의 출력을 추정해 볼 수 있습니다. 댓글의 내용과 동일하다면 틀린 것입니다. 올바른 결과는 다음과 같습니다.

[0, 1]
[1, 2, 0, 1, 2]
[0, 1, 0, 1]
로그인 후 복사

마지막 func(2)가 왜 이런지 궁금할 것입니다. 걱정하지 마세요. print(id(li))를 사용하여 디버깅해 보겠습니다.

def func(n, li = []):
print(id(li))
for i in range(n):
li.append(i)
print(li)

func(2)
func(3,li=[1,2])
func(2)
로그인 후 복사

결과는 다음과 같습니다.

140670243756736
[0, 1]
140670265684928
[1, 2, 0, 1, 2]
140670243756736
[0, 1, 0, 1]
로그인 후 복사

찾으셨나요? 첫 번째 func(2)와 두 번째 func(2)의 ID가 동일합니다. 이는 동일한 li를 사용함을 의미합니다. 이는 매개변수의 기본값이 가변 개체 논리임을 의미합니다. 모든 발신자 일반적으로 말하면 공유됩니다.

Python이 이런 식으로 설계된 이유를 더 자세히 알아보고 싶다면 http://cenalulu.github.io/python/default-mutable-arguments/

어떻게 피할 수 있나요?

가장 좋은 방법은 변경 가능한 객체를 함수 기본값으로 사용하지 않는 것입니다. 이런 식으로 사용해야 한다면 해결책은 다음과 같습니다.

def generate_new_list_with(my_list=None, element=None):
if my_list is None:
my_list = []
my_list.append(element)
return my_list
로그인 후 복사

이런 식으로 my_list의 기본값이 항상 []인 경우.

마지막으로

fib 함수의 구현이 인상적일 수 있다고 생각합니다. 하지만 이러한 사용은 매우 위험하며 자신의 코드에서 사용할 수 없다는 점에 유의하세요.

위 내용은 Python 함수 매개변수의 기본값이 변경 가능한 객체인 경우 주의해야 합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:51cto.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿