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

WBOY
Libérer: 2023-04-22 13:37:07
avant
1226 Les gens l'ont consulté

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]
Copier après la connexion

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]
Copier après la connexion

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]
Copier après la connexion

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)
Copier après la connexion

Le résultat est le suivant :

140670243756736
[0, 1]
140670265684928
[1, 2, 0, 1, 2]
140670243756736
[0, 1, 0, 1]
Copier après la connexion
.

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
Copier après la connexion

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!

Étiquettes associées:
source:51cto.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal