Question

Cela peut être pour la plupart des langues en général, mais je ne suis pas sûr. Je suis un débutant à Python et ont toujours travaillé sur des copies des listes en C # et VB. Mais en Python chaque fois que je passe une liste comme un argument et énumérer en utilisant un « pour i dans la gamme », puis changer la valeur de l'argument de la liste, les valeurs d'entrée change réellement la liste initiale. Je pensais que Python était censé passer des arguments par valeur par défaut de sorte qu'une fois la fonction terminée, j'ai encore les valeurs d'origine avant de la fonction appelée. Qu'est-ce que je rate? Merci!

Était-ce utile?

La solution

Python ne passe arguments par valeur, mais la valeur que vous recevez est une copie de la référence (soit dit en passant c'est exactement la même manière que C #, VB.NET, Java et se comportent aussi bien).

Ceci est la chose importante à retenir:

  

Les objets ne sont pas passés par référence -. Références d'objets sont passés par valeur

Puisque vous avez une copie de la référence, toute opération sur ce que les points de référence seront à tout comme si vous teniez la référence d'origine lui-même.

Autres conseils

Python - tout comme Java pour quoi que ce soit, mais scalaires primitifs, et comme C # et VB.NET faire pour les paramètres de nature par défaut, par opposition à boxed types et sur / ref parms - passe « par référence d'objet » (recherche cette phrase - c'est comment Guido, l'architecte Python et créateur, utilise pour expliquer ce argument- notion de croisement).

Chaque nom est une référence à un objet; faire passer un nom (ou toute autre expression) comme un argument est simplement crée encore une autre référence au même objet (que le corps de la fonction peut accéder par le nom du paramètre). ((Il n'y a pas une telle chose comme « une référence à un nom »: il y a noms , qui sont une sorte de référence à des objets, et l'objet - période)).

Lorsque vous passez un objet mutable, à savoir celui qui a des méthodes mutateurs (comme par exemple une liste), la fonction appelée peut muter l'objet en appelant, directement ou indirectement, ses méthodes de mutation. ((Par "indirectement", je veux dire "par les opérateurs" - par exemple:

somelist[len(somelist):] = [whatever]

est exactement identique à somelist.append(whatever).))

Si vous voulez passer une liste dans une fonction, mais faire pas la fonction doit pouvoir muter cette liste de quelque façon, vous devez passer une Copier de la liste au lieu de l'original -. comme en Java, C #, VB.NET

de très clair sur la distinction entre reconsolidation un nom et muter un objet . Reconsolidation le nom ( "barename", c'est - noms qualifiés sont différents ;-) uniquement affects nom - pas tout objet quoi que ce soit. Par exemple:

def f1(alist):
  alist = [23]

def f2(alist):
  alist[:] = [23]

Pouvez-vous faire la différence entre ces deux fonctions? On est reconsolidation barename alist - sans aucun effet que ce soit sur quoi que ce soit. L'autre est mutateurs (modifier, changer, ...) l'objet de la liste, il a reçu comme argument - en définissant son contenu à une liste d'un élément avec un int comme seul élément. Complètement, tout à fait différentes choses !!!

Pour ajouter à la réponse d'Andrew, vous devez faire explicitement une copie d'une liste si vous voulez conserver l'original. Vous pouvez le faire en utilisant le module copy, ou tout simplement faire quelque chose comme

a = [1,2]
b = list(a)

Comme les objets de copie implique généralement une baisse de performance, je trouve utile d'utiliser explicitement le module de copie dans mes projets plus importants. De cette façon, je peux facilement trouver tous les endroits où je vais utiliser un tas plus de mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top