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]

5voto

Amadan Points 41944

Ce n'est ni l'un ni l'autre. Il est appeler en partageant . J'ai également entendu l'expression "valeur de référence".

Également connu sous le nom de "call by object" ou "call by object-sharing", le call by sharing est une stratégie d'évaluation nommée pour la première fois par Barbara Liskov et al. pour le langage CLU en 1974. Elle est utilisée par des langages tels que Python, Iota, Java (pour les références d'objets), Ruby, JavaScript, Scheme, OCaml, AppleScript et bien d'autres. Cependant, le terme "call by sharing" n'est pas d'usage courant ; la terminologie n'est pas cohérente d'une source à l'autre. Par exemple, dans la communauté Java, on dit que Java est un appel par valeur, alors que dans la communauté Ruby, on dit que Ruby est un appel par référence, même si les deux langages présentent la même sémantique. L'appel par partage implique que les valeurs dans le langage sont basées sur des objets plutôt que sur des types primitifs, c'est-à-dire que toutes les valeurs sont "encadrées".

La sémantique de l'appel par partage diffère de celle de l'appel par référence en ce sens que les affectations aux arguments de la fonction à l'intérieur de la fonction ne sont pas visibles pour l'appelant (contrairement à la sémantique de l'appel par référence), de sorte que, par exemple, si une variable a été transmise, il n'est pas possible de simuler une affectation sur cette variable dans la portée de l'appelant. Cependant, puisque la fonction a accès au même objet que l'appelant (aucune copie n'est faite), les mutations de ces objets, si les objets sont mutables, au sein de la fonction sont visibles pour l'appelant, ce qui peut sembler différent de la sémantique d'appel par valeur. Les mutations d'un objet mutable au sein de la fonction sont visibles pour l'appelant car l'objet n'est pas copié ou cloné - il est partagé.

4voto

kindall Points 60645

Il s'agit d'un passage par valeur, où toutes les valeurs sont des pointeurs vers des objets. On pourrait penser que cela implique que l'on peut utiliser le pointeur passé pour modifier la variable de l'appelant, ce qui en fait un passage par référence, mais ce n'est pas le cas, donc ce n'est pas le cas.

Pour comprendre comment fonctionne le passage de valeurs en Python, il est essentiel de savoir qu'il n'existe pas de valeurs "non encadrées" (sans objet). Les entiers sont des objets, et une variable qui "contient" un entier est en fait un pointeur vers un objet entier stocké ailleurs que dans la variable. Il en va de même pour les flottants et les booléens.

En Python, les variables ne "détiennent" pas vraiment de valeurs comme c'est le cas, par exemple, en C. L'affectation consiste donc toujours à faire pointer le nom de la variable vers un objet différent.

Si un objet transmis à une fonction est mutable, la fonction peut le modifier, mais elle doit le faire sans changer l'objet vers lequel son ou ses noms pointent. Par exemple :

some_digits_of_pi = [3, 1, 4, 1, 5, 9, 2, 7]

def extend_pi(x):
    x[-1] = 6
    x += [5, 3, 5, 9]

Il s'agit ici d'une mutation x à l'intérieur de la fonction. (Pour une liste, += est essentiellement list.extend .) Puisque x n'est jamais modifié pour pointer vers un objet différent, les modifications sont apportées à la liste qui a été transmise. Le nom some_digits_of_pi fait référence au même objet que celui qui est modifié dans la fonction, de sorte que l'appelant verra que sa liste de ce nom a été modifiée.

Si l'on écrit x = [2, 7, 1, 8, 2, 8, 1, 8] à la fin de la fonction, cela créerait un nouvel objet liste et pointerait le nom local x à ce sujet. Cela ne change pas ce que la variable de l'appelant pointe vers, donc cette liste n'est pas modifiée par cette déclaration.

En d'autres termes, vous ne pouvez pas faire de la de l'appelant variable ( some_digits_of_pi dans ce cas) pointent vers un objet différent. Si vous modifiez x pour pointer vers un objet différent à l'intérieur de la fonction, seulement x pointe vers cet objet.

Les nombres, les chaînes de caractères, les tuples et autres fonctionnent exactement de la même manière. Un pointeur sur l'objet est transmis ; si vous modifiez la valeur de l'argument à l'intérieur de la fonction, il est amené à pointer sur un objet différent, ce qui ne modifie naturellement pas la variable de l'appelant. Il s'agit seulement d'une modification de la variable de l'appelant. semble parce que ces types d'objets ne sont pas mutables et qu'il n'existe aucun moyen de les modifier sur place.

Un autre point de confusion réside dans le fait qu'il regards comme int et list ont tous deux += mais il arrive que += sur un int fait quelque chose de très différent de ce que la même opération fait sur un list . Sur une liste, += renvoie le même objet liste (modifié), alors que sur un entier, il peut renvoyer un objet complètement différent (puisque les entiers sont immuables).

2voto

viraptor Points 12779

La dénomination des appels est différente selon l'interlocuteur. Ce qui n'est pas du tout le cas, c'est le "pass-by-reference".

Tant sur le plan technique que sur celui de la d'après les documents python est de type "pass-by-value".

[...] Sinon, la valeur de l'argument est placée dans l'emplacement, le remplissant (même si l'expression est None, elle remplit l'emplacement). Lorsque tous les arguments ont été traités, les emplacements qui ne sont pas encore remplis le sont avec la valeur par défaut correspondante de la définition de la fonction. [...]

Ce n'est pas parce que les valeurs sont en fait des références que les gens discutent de la convention et définissent de nouveaux noms pour décrire ce qui se passe d'un point de vue plus pratique. Call by value reference, by sharing, by handle, etc. sont autant de noms différents que l'on peut utiliser.

2voto

zondo Points 11370

Je n'en ai jamais connu le nom, mais selon Amadan, il s'agit d'un "appel au partage". Je vais faire une analogie pour faciliter la compréhension.

Disons que j'ai un chien et que je l'appelle "Brutus". J'emmène Brutus en promenade et je rencontre mon voisin Sam. Sam n'aime pas le nom que j'ai choisi et appelle mon chien "Dodo". S'il plante un couteau dans Dodo, cela affecte bien sûr Brutus puisqu'il s'agit du même chien. Supposons qu'il ne le fasse pas et que Billy, un autre voisin, se promène avec son chien. Sam change d'avis et décide que le chien de Billy est Dodo. S'il plante un couteau dans Dodo, cela n'affecte pas Brutus parce qu'il s'agit de chiens différents.

Votre fonction est similaire. mylist se dirige vers votre fonction et votre fonction décide de l'appeler mylist du même nom. Votre fonction décide alors que [1,2,3,4] es mylist . Vous avez écarté l'original et défini une nouvelle liste. Votre réaffectation n'affecte pas la liste d'origine.

1voto

haifzhan Points 724

mylist = [1,2,3,4] est créé à l'intérieur de changeme() mylist est une variable locale, ce n'est pas le paramètre que vous avez passé, même s'il porte le même nom que l'argument. Elle ne fait pas référence au paramètre mylist

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