5 votes

Comment peut-on parler de passage par référence ?

Según cette Python utilise la méthode "Pass By Reference".

Ils donnent ensuite l'exemple suivant. Sur quelle planète se trouve ce "Pass By Reference" ? Pour moi, il s'agit d'un cas flagrant de "Pass By Value" (passage par la valeur).

Réflexions ?

def changeme( mylist ):
   mylist = [1,2,3,4];
   print "Values inside the function: ", mylist
   return

mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

Le paramètre mylist est local à la fonction changeme. La modification de mylist au sein de la fonction n'affecte pas mylist. La fonction n'accomplit rien et finalement cela produirait le résultat suivant :

# Values inside the function:  [1, 2, 3, 4]
# Values outside the function:  [10, 20, 30]

0voto

Serdalis Points 5376

Conformément à la réponse de @Amadan, Python utilise Appel par partage .

Dans la fonction, vous avez réaffecté la référence à une nouvelle liste, de sorte qu'elle ne pointe plus vers la liste que vous avez transmise.

Vous pouvez voir ce qui se passe avec le code suivant :

def changeme( mylist ):
   print locals()  # will show mylist value in function.
   mylist = [1,2,3,4];
   print locals()  # will show mylist value in function.
   print globals()['mylist'] # will show global mylist value
   print "Values inside the function: ", mylist
   return

Où vous verrez la valeur de mylist change après l'affectation dans la liste des locaux, mais la référence globale reste la même.

-1voto

Matt Messersmith Points 4399

Python, en ce qui me concerne, est exactement comme Java, dans la mesure où toutes les fonctions (méthodes) sont de type "pass-by-value". Voir cette fameuse réponse . L'inconvénient de "l'appel par partage" est qu'il vous fait penser que quelque chose de différent se produit pour différents types (c'est-à-dire que les types mutables se comportent différemment dans les appels de fonction que les types immuables). Ce n'est pas du tout le cas, la même chose se produit chaque fois que vous appelez une fonction. De plus, aucun manuel que j'ai lu ne mentionne le concept, je pense que pass-by-value et pass-by-reference sont des terminologies beaucoup plus populaires.

Comment fonctionne le passage par la valeur ?

Elle fonctionne en copiant la "valeur" qui a été transmise à la fonction avant de la modifier dans la fonction. Prenons l'exemple suivant :

my_int = 4
def pass_by_value(value):
    value += 1
    return value
print pass_by_value(my_int)
print my_int

cette sortie :

5
4

Observez que la valeur de my_int n'a pas changé . Il est resté à 4 même si la fonction a incrémenté la valeur qui a été transmise pour être 5 . C'est parce qu'il a été copié. Il y a là plusieurs subtilités sur lesquelles nous reviendrons. Soyez indulgent avec moi.

Passer par valeur sur une liste

my_list = [1,2,3]
def pass_by_value_list(li):
    li.append(4)
    return li
print pass_by_value_list(my_list)
print my_list

cette sortie :

[1, 2, 3, 4]
[1, 2, 3, 4]

Qu'est-ce que c'est que ça ? La valeur de my_list a changé. Vous venez de dire plus haut que la méthode "pass-by-value" copie la valeur ! Par conséquent, my_list n'aurait pas dû changer !!!

Le premier exemple était trop subtil. Je n'ai pas défini correctement la "valeur" copiée. Il s'avère que la valeur copiée est pas les données mais plutôt, l'endroit où les données sont stockées . En général, les programmeurs C/C++ appellent cela un pointeur o adresse . Reprenons les exemples, mais modifions-les un peu pour mieux comprendre.

Comment fonctionne le passage par la valeur ? Version 2.0 :

my_int = 4
def pass_by_value(value):
    print "Address of parameter before += is: ", id(value)
    value += 1
    print "Address of parameter after += is: ", id(value)
    return value
print "Address of parameter outside of the function is: ", id(my_int)
pass_by_value(my_int)

Lorsque j'ai exécuté cette opération, j'ai obtenu le résultat suivant :

Address of parameter outside of the function is:  40592528
Address of parameter before += is:  40592528
Address of parameter after += is:  40592504

On dirait que l'adresse du paramètre avant l'élément += était 40592528. Il s'agit également de la même "valeur" que celle du paramètre extérieur à la fonction ! Mais après l'opérateur += la "valeur" a changé à l'intérieur la fonction ! Cependant, ce changement d'adresse n'a pas été propagé à l'extérieur la fonction, car le adresse es pass-by-value . La nouvelle adresse à l'intérieur de la fonction est 40592504 (différente de 40592528, bien que proche). Pour faire court, la fonction += crée un nouveau int et n'opère pas sur les données de l'adresse transmise à la fonction.

Passage par valeur sur une liste, Version 2.0 :

my_list = [1,2,3]
def pass_by_value_list(li):
    print "Address of parameter before .append() is: ", id(li)
    li.append(4)
    print "Address of parameter after .append() is: ", id(li)
    return li
print "Address of parameter outside of the function is: ", id(my_list)
pass_by_value_list(my_list)

cette sortie :

Address of parameter outside of the function is:  110841160
Address of parameter before .append() is:  110841160
Address of parameter after .append() is:  110841160

C'est différent du cas des nombres entiers. On dirait que toutes les adresses sont les mêmes ! En effet, cela diffère du cas des nombres entiers. Les append opère sur une liste en place et ne renvoie pas une nouvelle liste. C'est la raison pour laquelle vous voyez un changement dans my_list en dehors de la fonction. append modifie la liste à l'adresse qui a été transmise à la fonction, de sorte que les données sont modifiées partout dans le programme. Ce qui n'a pas changé, en revanche, c'est l'adresse.

Observez que :

my_list = [1,2,3]
def dont_change_the_list(li):
    li.append(4)
    li = []
    return li
print dont_change_the_list(my_list)
print my_list

sorties

[]
[1, 2, 3, 4]

En d'autres termes, la modification de la liste à l'intérieur de la fonction n'a pas été propagée à l'extérieur de la fonction, même si cela semblait être le comportement que nous avions observé auparavant . En effet, l'énoncé li = [] modifie l'adresse de li mais nous avons copié l'adresse avant l'exécution de la fonction. L'adresse du paramètre est la "valeur" qui est copiée, et il n'est pas possible de la modifier à l'intérieur d'une fonction. . Cela n'a donc pas modifié les données dans my_list dans le programme principal.

L'essentiel : Python utilise toujours la sémantique "pass-by-value" pour ses appels de fonction. La valeur est simplement l'adresse de l'objet qui a été passé, et non les données de l'objet qui a été passé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X