web-dev-qa-db-fra.com

Passer des valeurs dans Python

Lorsque vous passez une collection comme list, array à une autre fonction en python, en fait-elle une copie, ou est-ce juste un pointeur?

57
Joan Venge

Python transmet les références aux objets par valeur .

Python transmet les références aux objets par valeur (comme Java), et tout ce qui se trouve dans Python est un objet. Cela semble simple, mais vous remarquerez que certains types de données semblent présenter un passage -caractéristiques de la valeur, tandis que d'autres semblent agir comme un passage par référence ... quel est le problème?

Il est important de comprendre les objets mutables et immuables. Certains objets, comme les chaînes, les tuples et les nombres, sont immuables. Les modifier à l'intérieur d'une fonction/méthode créera une nouvelle instance et l'instance d'origine en dehors de la fonction/méthode ne sera pas modifiée. D'autres objets, comme les listes et les dictionnaires, peuvent être modifiés, ce qui signifie que vous pouvez modifier l'objet sur place. Par conséquent, la modification d'un objet à l'intérieur d'une fonction/méthode modifiera également l'objet d'origine à l'extérieur.

80
Stephen

Le fait est que tout le concept de référence/valeur ne rentrera pas dans python. Python n'a pas de "valeur" de variable. Python n'a que des objets et des noms qui font référence à des objets).

Ainsi, lorsque vous appelez une fonction et mettez un "nom" entre parenthèses, comme ceci:

def func(x): # defines a function that takes an argument
    ... # do something here

func(myname) # calling the function

L'objet réel que myname pointe est passé, pas le nommynamelui-même. A l'intérieur de la fonction n autre nom (x) est donné pour faire référence au même objet passé.

Vous pouvez modifier l'objet à l'intérieur de la fonction s'il est modifiable, mais vous ne pouvez pas changer ce vers quoi le nom extérieur pointe. C'est la même chose qui se produit quand vous le faites

anothername = myname

Je peux donc répondre à votre question par:

c'est "passer par valeur" mais toutes les valeurs ne sont que des références à des objets.

69
nosklo

Les réponses ici ont été utiles, mais je trouve la nécessité de montrer cette fine distinction que je n'ai pas vu couverte, que je me suis prouvé avec l'expérience CL suivante:

  1. Un objet immuable SEUL NE PEUT PAS être changé dans un appel de fonction. (les réponses ont jusqu'à présent dit beaucoup ...)
  2. MAIS, un objet immuable CONTENU DANS un objet mutable PEUT être réassigné dans un appel de méthode.

'num' ne change pas ici car c'est un objet Number immuable [supporte mon point 1.]:

def incr_num(num):
    num += 1

num = 0

num
0

incr_num(num)

num
0

'list [0]' est aussi ici un objet Number immuable.

def incr_list(list):
    list[0] += 1

list = [0]

list[0]
0

incr_list(list)

list[0]
1

Alors, comment 'list [0]', étant un objet Number immuable, a-t-il changé (prend en charge mon point 2.) alors que l'objet Number 'num' de l'exemple ci-dessus n'a pas changé? L'objet Number immuable ' list [0] 'est contenu dans l'objet liste mutable' list ', tandis que' num 'du 1er exemple est juste un objet Number non contianed.

Bien que bien intentionnée, je pense @ Stephen Pape la réponse la mieux notée (citée ci-dessous), et certaines autres similaires, n'étaient pas totalement correctes (et cela m'a motivé à écrire cette réponse):

Certains objets, comme les chaînes, les tuples et les nombres, sont immuables. Les modifier à l'intérieur d'une fonction/méthode créera une nouvelle instance et l'instance d'origine en dehors de la fonction/méthode ne sera pas modifiée.

Ma deuxième expérience de code ci-dessus montre un objet Number ('list [0]') en cours de modification dans une méthode, puis l'instance d'origine en dehors de la fonction a changé.

23
cellepo

Une référence est passée, mais si le paramètre est un objet immuable, sa modification dans la méthode créera une nouvelle instance.

6
anthony

L'objet est passé. Pas une copie, mais une référence à l'objet sous-jacent.

4
S.Lott

Je recommanderais également de regarder le module copy:

documentation Python pour copie

Il vous aidera à comprendre les problèmes sous-jacents et à l'utiliser pour effectuer votre propre copie en profondeur.

3
Matt

Par référence:

>>> x = [0,1,2,3]
>>> def foo(x_list):
    x_list[0] = 1


>>> foo(x)
>>> x
[1, 1, 2, 3]
2
Harper Shelby

S'il vous plaît permettez-moi de donner un humble exemple

def swap(a, b):
    x = a
    print id(x)
    print id(a)
    print id(b)
    a = b

    print id(a)
    b = x
    print id(b)
    a[0]= '20'




var1 = ['1','2','3','4']
var2 = ['5','6','7','8','9']
print id(var1)
print id(var2)

swap(var1, var2)

print id(var1)
print id(var2)
print var1
print var2

qui produit le résultat suivant

28329344 var1 28331264 var2 28329344 x 28329344 a 28331264 b Après a = b 28331264 a après b = x 28329344 b après retour 28329344 var1 28331264 var2 ['1', '2', '3', '4'] ['20', "6", "7", "8", "9"]

Correspondance avec les adresses mémoire 28329344 28331264 var1 var2 abx Après a = ba Après b = xb Après a [0] = '20' [0] = '20' Après retour ['1', '2', '3', ' 4 '] [' 20 ',' 6 ',' 7 ',' 8 ',' 9 ']

0
Antonio Leite