Maison  >  Article  >  développement back-end  >  Il faut être prudent lorsque la valeur par défaut des paramètres de la fonction Python est un objet mutable

Il faut être prudent lorsque la valeur par défaut des paramètres de la fonction Python est un objet mutable

WBOY
WBOYavant
2023-04-22 13:37:071227parcourir

J'ai vu que les objets variables sont transmis aux valeurs par défaut des paramètres de la fonction Python pour accélérer la récursion de la fonction Fibonacci. Le code est le suivant :

def fib(n, cache={0: 0, 1: 1}):
if n not in cache:
cache[n] = fib(n - 1) + fib(n - 2)
return cache[n]

N'est-ce pas très nouveau, cela peut en fait l'être. comme ça, la vitesse est vraiment très rapide, Les résultats d'exécution sont les suivants :

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

Cependant, je vous conseille de ne pas faire cela, et l'IDE vous dira également que c'est mauvais de le faire :

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

C'est parce que tout est un objet, et les fonctions Python sont aussi des objets, et les paramètres sont La valeur par défaut est l'attribut de l'objet. La valeur par défaut du paramètre est déjà liée à la fonction lors de la phase de compilation. est un objet variable, la valeur par défaut du paramètre de la fonction Python sera stockée et partagée par tous les appelants, c'est-à-dire si la valeur du paramètre par défaut d'une fonction est un objet variable, tel que List ou Dict, et que l'appelant A modifie alors l'appelant B verra le résultat modifié de A lors de l'appel. Un tel modèle produira souvent des résultats inattendus, comme l'algorithme de fib ci-dessus, mais il s'agit plutôt d'un bug.

Vous pouvez jeter un œil à ce code simple :

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]

Vous pouvez d'abord estimer le résultat de ce code. S'il est le même que celui dans les commentaires, alors vous vous trompez. Le résultat correct est :

[0, 1]
[1, 2, 0, 1, 2]
[0, 1, 0, 1]

Vous vous demandez peut-être pourquoi la dernière func(2) est comme ça. Ne vous inquiétez pas, imprimons(id(li)) pour le déboguer :

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)

Le résultat est le suivant :

140670243756736
[0, 1]
140670265684928
[1, 2, 0, 1, 2]
140670243756736
[0, 1, 0, 1]
.

L'avez-vous trouvé ? Les identifiants de la première func(2) et de la deuxième func(2) sont les mêmes, ce qui indique qu'ils utilisent le même li. Cela signifie que la valeur par défaut du paramètre est une logique d'objet variable, pour. tous les appelants. De manière générale, il est partagé.

Si vous souhaitez approfondir pourquoi Python est conçu de cette façon, vous pouvez consulter http://cenalulu.github.io/python/default-mutable-arguments/

Comment l'éviter ?

La meilleure façon est de ne pas utiliser d'objets mutables comme valeurs par défaut de la fonction. Si vous devez l'utiliser de cette façon, voici une solution :

def generate_new_list_with(my_list=None, element=None):
if my_list is None:
my_list = []
my_list.append(element)
return my_list

De cette façon, si la valeur par défaut de my_list est toujours [].

Enfin

Je pense que l'implémentation de la fonction fib peut vous impressionner, mais veuillez noter qu'une telle utilisation est très dangereuse et ne peut pas être utilisée dans votre propre code.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer