Les arguments par défaut de Python ne sont pas initialisés à chaque appel

J'écrivais du code en Python et je me suis dit "Est-ce vraiment?"

def wrap_list(value, base_list = []):
    base_list.append(value)
    return base_list

Supposons que vous ayez un code comme celui-ci. Si vous appelez cela plusieurs fois, en omettant le deuxième argument:

print(wrap_list(1)) # => [1]
print(wrap_list(2)) # => [1, 2]

Le résultat est. Je veux que ce soit «[2]» la deuxième fois.

Vous pouvez voir ce qui se passe en affichant l'ID de l'objet avec la fonction ʻid`.

def wrap_list(value, base_list = []):
    print(id(base_list)) # debug print
    base_list.append(value)
    return base_list

wrap_list(1) # => 4373211008
wrap_list(2) # => 4373211008

L'ID d'objet de base_list est le même dans les deux appels. En d'autres termes, une liste vide n'est pas générée pour chaque appel, mais une seule fois.

Au fait, je l'ai aussi essayé sur Ruby:

def wrap_list(value, base_list = [])
  puts base_list.object_id
  base_list << value
end

wrap_list(1) # => 70218064569220
wrap_list(2) # => 70218064588580

Cela semble être généré pour chaque appel.

Je ne pense pas que j'écrirais du code comme celui ci-dessus en Python:

class WrappedList(object):
    def __init__(self, initial = []):
        self.list = initial

    def append(self, value):
        self.list.append(value)

Bien sûr, la même chose se produit dans de tels cas, vous devez donc faire attention.

Le problème fondamental est qu'il n'est pas initialisé pour chaque appel et que la solution de contournement est simplement "n'effectuez pas d'opérations destructives". Si vous avez besoin d'une opération destructive, vous pouvez définir l'argument par défaut lui-même sur «Aucun», et s'il est «Aucun», initialisez-le avec une liste vide.

Recommended Posts

Les arguments par défaut de Python ne sont pas initialisés à chaque appel
Impossible d'utiliser les commandes python et pip sur CentOS (RHEL) 8
a () et a .__ call__ () ne sont pas équivalents
Construire un environnement Python sur Ubuntu (lorsque pip n'était pas la valeur par défaut)
Appeler C / C ++ depuis Python sur Mac
Tous les arguments Python sont passés par référence
Virtualenv ne fonctionne pas sur Python 3.5 (Windows)
Jinja2 2.9.6 ne fonctionne pas sur la série Lambda Python 3
Quand les arguments par défaut seront-ils liés en python? Lorsque les variables sont liées dans l'évaluation différée de la fermeture.