Comment puis-je passer une variable par référence?
La documentation Python semble pas clair quant à savoir si les paramètres sont passés par référence ou la valeur, et le code suivant donne la valeur inchangée "Original"
class PassByReference:
def __init__(self):
self.variable = 'Original'
self.change(self.variable)
print(self.variable)
def change(self, var):
var = 'Changed'
Est-il quelque chose que je peux faire pour passer la variable par référence?
Pour un court, des explications, des précisions, voir la première réponse de ce stackoverflow question. Comme les chaînes sont immuables, ils ne seront pas modifiées et une nouvelle variable sera créé, ainsi l ' "extérieur" de la variable a toujours la même valeur.
Le code de la BlairConrad la réponse est bonne, mais l'explication fournie par DavidCournapeau et DarenThomas est correct.
Avant de lire la réponse sélectionnée, veuillez tenir compte de la lecture de ce court texte d'Autres langues ont "variables", Python a "nom". Pense à propos de "noms" et les "objets" au lieu de "variables" et "références" et vous devriez éviter beaucoup de problèmes similaires.
Pourquoi cette inutilement de l'utiliser en classe? Ce n'est pas Java 😛
une autre solution consiste à créer un wrapper "référence" comme ceci: ref = type(", (), {'n':1}) stackoverflow.com/a/1123054/409638
Le code de la BlairConrad la réponse est bonne, mais l'explication fournie par DavidCournapeau et DarenThomas est correct.
Avant de lire la réponse sélectionnée, veuillez tenir compte de la lecture de ce court texte d'Autres langues ont "variables", Python a "nom". Pense à propos de "noms" et les "objets" au lieu de "variables" et "références" et vous devriez éviter beaucoup de problèmes similaires.
Pourquoi cette inutilement de l'utiliser en classe? Ce n'est pas Java 😛
une autre solution consiste à créer un wrapper "référence" comme ceci: ref = type(", (), {'n':1}) stackoverflow.com/a/1123054/409638
OriginalL'auteur David Sykes | 2009-06-12
Vous devez vous connecter pour publier un commentaire.
Arguments sont transmis par cession. La justification de cette est double:
Donc:
Si vous passez un mutable objet dans une méthode, la méthode renvoie une référence à ce même objet et vous pouvez les transformer à votre guise, mais si vous réassocier la référence à la méthode, à l'extérieur de la portée ne sait rien sur elle, et après vous avez terminé, la référence externe sera toujours le point à l'objet d'origine.
Si vous passez un immuable objet à une méthode, vous ne pouvez pas relier la référence externe, et vous ne pouvez même pas la mutation de l'objet.
Pour le rendre encore plus clair, nous allons donner quelques exemples.
La liste - une mutable type
Essayons de modifier la liste qui a été transmis à une méthode:
De sortie:
Depuis le paramètre transmis est une référence à
outer_list
, pas une copie de celui-ci, nous pouvons utiliser la mutation de la liste des méthodes pour changer et avoir des changements indiqués dans l'extérieur de la portée.Maintenant, nous allons voir ce qui se passe quand on essaie de changer la référence qui a été transmis en tant que paramètre:
De sortie:
Depuis le
the_list
paramètre est passé par valeur, l'attribution d'une nouvelle liste, il n'a eu aucun effet que le code en dehors de la méthode pouvait voir. Lethe_list
était une copie de laouter_list
de référence, et nous avons euthe_list
point à une nouvelle liste, mais il n'y avait aucun moyen de changer de oùouter_list
pointu.Chaîne immuable type
Il est immuable, donc il n'y a rien que nous pouvons faire pour changer le contenu de la chaîne
Maintenant, essayons de changer la référence
De sortie:
De nouveau, depuis le
the_string
paramètre est passé par valeur, l'attribution d'une nouvelle chaîne, il n'a eu aucun effet que le code en dehors de la méthode pouvait voir. Lethe_string
était une copie de laouter_string
de référence, et nous avons euthe_string
point d'une nouvelle chaîne, mais il n'y avait aucun moyen de changer de oùouter_string
pointu.J'espère que cela efface les choses un peu.
EDIT: Il a été noté que ce n'est pas répondre à la question que @David initialement demandé, "Est-il quelque chose que je peux faire pour passer la variable par référence réel?". Nous allons travailler sur.
Comment contourner ce problème?
@Andrea réponse de la montre, vous pourriez revenir à la nouvelle valeur. Cela ne change pas la façon dont les choses se sont passées, mais ne vous permettent d'obtenir l'information que vous voulez de retour:
Si tu voulais vraiment éviter d'utiliser une valeur de retour, vous pouvez créer une classe afin de conserver votre valeur et la passer dans la fonction ou l'utilisation d'une classe existante, comme une liste:
Bien que cela semble un peu lourd.
Je ne suis pas sûr de comprendre vos termes. J'ai été hors de la C jeu pendant un certain temps, mais à l'époque, quand j'étais en elle, il n'y a pas de "passage par référence" - vous pouvez passer des choses, et c'était toujours le passage par valeur, donc tout ce qui était dans la liste des paramètres a été copié. Mais parfois, la chose est un pointeur, on peut suivre à l'élément de mémoire (primitive, tableau, structure, peu importe), mais vous ne pouvez pas modifier le pointeur qui a été copié à partir de l'extérieur de la portée - quand vous avez été fait avec la fonction, l'original, le pointeur encore souligné à la même adresse. C++ a introduit des références, qui se sont comportés différemment.
Bowling je n'ai pas vraiment comment ce que vous dites est pertinent, dans un sens pratique, à cette réponse. Si un Python de nouveaux arrivants voulu savoir sur la passant par ref/val, puis la à retenir de cette réponse, c'est: 1- Vous utiliser la référence d'une fonction reçoit comme arguments, de modifier l '"extérieur" de la valeur d'une variable, aussi longtemps que vous n'avez pas réaffecter le paramètre de se référer à un nouvel objet. 2- l'Affectation à une immuable type toujours créer un nouvel objet, qui rompt la référence que vous aviez à l'extérieur de la variable.
vous avez besoin d'un meilleur exemple - les numéros sont également des objets immuables en Python. D'ailleurs, ça ne serait pas vrai de dire que aucun affectation, sans subscripting sur le côté gauche du signe égal, permettra de réaffecter le nom d'un nouvel objet de savoir s'il est immuable ou pas?
def Foo(alist): alist = [1,2,3]
sera pas modifier le contenu de la liste d'appelants point de vue.-1. Le code est bon, l'explication de la manière dont est complètement faux. Voir les réponses par DavidCournapeau ou DarenThomas pour corriger les explications du pourquoi.
OriginalL'auteur Blair Conrad
Le problème vient d'une incompréhension de ce que sont les variables en Python. Si vous avez utilisé pour la plupart des langues, vous avez un modèle mental de ce qui se passe dans la séquence suivante:
Vous croyez que
a
est un emplacement de mémoire qui stocke la valeur1
, puis est mis à jour pour stocker la valeur2
. Ce n'est pas la façon dont les choses fonctionnent en Python. Plutôt,a
commence comme une référence à un objet avec la valeur1
, puis se réaffecté comme une référence à un objet avec la valeur2
. Ces deux objets peuvent continuer à coexister, même sia
ne fait pas référence à la première; en fait, ils peuvent être partagés par un certain nombre d'autres références au sein du programme.Lorsque vous appelez une fonction avec un paramètre, une nouvelle référence est créé, qui se réfère à l'objet passé en. Ceci est distinct de la référence qui a été utilisé dans l'appel de la fonction, donc il n'y a aucun moyen de mise à jour de la référence et de faire référence à un nouvel objet. Dans votre exemple:
self.variable
est une référence à l'objet de type string'Original'
. Lorsque vous appelezChange
vous créez une deuxième référencevar
à l'objet. À l'intérieur de la fonction, vous pouvez réaffecter la référencevar
à un autre objet de type string'Changed'
, mais la référenceself.variable
est distinct et ne change pas.La seule façon de contourner cela est de faire passer un objet mutable. Parce que les deux références se rapportent au même objet, toute modification de l'objet sont reflétées dans les deux endroits.
Mais comment pouvez-vous réaffecter la référence? J'ai pensé que vous ne pouvez pas changer l'adresse de 'var', mais que votre chaîne a "Changé" allait être stockés dans l' 'var' adresse de mémoire. Votre description donne l'impression d'une "Changé" et "Original" appartiennent à différents endroits dans la mémoire et vous venez de passer 'var' à une adresse différente. Est-ce exact?
Je pense que vous êtes obtenir. "Changé" et "Original", différent de la chaîne des objets situés à différentes adresses de la mémoire et " var " des changements de pointage pour l'un de pointage à l'autre.
c'est la meilleure explication et doit être accepté de répondre. Court, concis et clair. D'autres pièces nouvelles, confusion des termes comme "de référence est passé par valeur', 'appel de l'objet", etc. Cette réponse efface tout. Merci 🙂
en termes simples, une référence est quelque chose qui "renvoie" à un objet. La représentation physique de qui est le plus probable d'un pointeur, mais ce n'est qu'un détail d'implémentation. C'est vraiment une notion abstraite à cœur.
OriginalL'auteur Mark Ransom
J'ai trouvé les autres réponses, plutôt long et compliqué, j'ai donc créé ce schéma simple pour expliquer la façon Python traite des variables et des paramètres.
Très élégante, une explication. Je pense que les autres réponses sont longues et compliquées. Good job!!!
Il n'a pas d'importance si Un est mutable ou pas. Si vous affectez quelque chose de différent de B, ne change pas. Si un objet est mutable, vous pouvez les transformer, c'est sûr. Mais qui n'a rien à voir avec l'affectation d'un nom..
Merci pour la mise à jour, beaucoup mieux! Ce qui confond la plupart des gens est d'affectation à un abonnement; par exemple,
B[0] = 2
, par rapport à l'affectation directe,B = 2
."Une est attribuée à B." n'Est-ce pas ambigu? Je pense en anglais ordinaire, ce qui peut signifier soit
A=B
ouB=A
.OriginalL'auteur Zenadix
Il n'est ni passer par valeur ou par référence - c'est l'appel-par-objet. Voir, par Fredrik Lundh:
http://effbot.org/zone/call-by-object.htm
Ici est un important citation:
Dans votre exemple, lorsque le
Change
méthode est appelée--un espace de noms est créé pour elle; etvar
devient un nom, dans cet espace, de l'objet de type string'Original'
. L'objet a alors un nom dans deux espaces de noms. Ensuite,var = 'Changed'
lievar
à une nouvelle chaîne de l'objet, et donc la méthode de l'espace de noms oublie'Original'
. Enfin, cet espace de nom est oublié, et la chaîne'Changed'
avec elle.Ce n'est pas comme java. L'un des cas où il n'est pas le même pour des objets immuables. Pensez-triviaux de la fonction lambda x: x. Appliquer ce pour x = [1, 2, 3] et x = (1, 2, 3). Dans le premier cas, la valeur retournée sera une copie de l'entrée, et identique dans le second cas.
Non, c'est exactement comme Java de la sémantique des objets. Je ne suis pas sûr de ce que tu veux dire par "Dans le premier cas, la valeur retournée sera une copie de l'entrée, et identique dans le second cas." mais cette affirmation semble être manifestement erronées.
C'est exactement le même que dans Java. Les références de l'objet sont passés par valeur. Toute personne qui pense différemment de connecter le code Python pour un
swap
fonction qui permet de permuter deux références, comme ceci:a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42]
C'est exactement le même que Java, lorsque vous transmettez des objets en Java. Cependant, Java ont aussi primitives, qui sont passés par copie de la valeur de la primitive. Ainsi, ils diffèrent dans ce cas.
OriginalL'auteur David Cournapeau
Penser à des trucs d'être passé par cession plutôt que par référence/par valeur. De cette façon, il est toujours clair, ce qui se passe tant que vous comprenez ce qui se passe pendant le fonctionnement normal de l'affectation.
Donc, lors du passage d'une liste à une fonction/méthode, la liste est attribué le nom du paramètre. L'ajout à la liste de résultat dans la liste en cours de modification. Réassigner la liste à l'intérieur de la fonction ne changera pas la liste d'origine, depuis:
Depuis immuable types ne peuvent pas être modifiés, ils semblent comme être passé par valeur - passage d'un int dans une fonction signifie que l'attribution de l'int pour les fonctions de paramètre. Vous ne pouvez jamais réaffecter, mais il ne changera pas le originial variables de valeur.
OriginalL'auteur Daren Thomas
Effbot (aka Fredrik Lundh) a décrit Python variable passant du style que l'appel-par-objet: http://effbot.org/zone/call-by-object.htm
Les objets sont alloués sur le tas et des pointeurs vers eux peuvent être envoyés n'importe où.
Lorsque vous effectuez une assignation comme
x = 1000
, d'une entrée de dictionnaire est créé que les cartes de la chaîne de caractères "x" dans l'espace de noms courant vers un pointeur vers l'objet integer contenant un millier.Lorsque vous mettez à jour "x" avec
x = 2000
, new integer objet est créé et le dictionnaire est mis à jour pour pointer vers le nouvel objet. La vieille d'un millier d'objet est le même (et peut ou peut ne pas être en vie, selon que quelque chose d'autre se réfère à l'objet).Lorsque vous effectuez une nouvelle affectation, tels que
y = x
, une nouvelle entrée dans le dictionnaire "y" est créé, qui pointe vers le même objet que l'entrée "x".Objets comme les chaînes et les nombres entiers sont immuable. Cela signifie simplement qu'il n'existe pas de méthodes qui permettent de modifier l'objet après qu'il a été créé. Par exemple, une fois que l'objet integer mille est créé, il ne changera jamais. Math se fait par la création de nouvelles integer objets.
Objets comme les listes sont mutable. Cela signifie que le contenu de l'objet peut être modifié par n'importe quoi pour le pointage de l'objet. Par exemple,
x = []; y = x; x.append(10); print y
imprime[10]
. La liste vide est créé. Les deux "x" et "y" le point sur la même liste. Le ajouter méthode de mutation (mises à jour) la liste d'objet (comme l'ajout d'un enregistrement dans une base de données), et le résultat est visible à la fois "x" et "y" (comme une base de données mise à jour devrait être visible à chaque connexion à la base de données).Espère que précise la question pour vous.
id()
fonction retourne le pointeur (la référence d'objet de valeur, comme pepr réponse suggère?Oui, Disponible dans le id() renvoie l'adresse. Mais dans d'autres pythons tels que PyPy et Jython, le id() est juste un identificateur d'objet unique.
cette réponse, plus l'indice de l'utilisation de l'id() qui indique quand une mission se lie un nom existant à un nouvel objet, est la meilleure de tout le fil.
OriginalL'auteur Raymond Hettinger
Techniquement, Python utilise toujours passer par des valeurs de référence. Je vais répéter mon autre réponse à l'appui de mon affirmation.
Python utilise toujours passer par des valeurs de référence. Il n'y a pas d'exception. Toute affectation de variable signifie copie de la valeur de référence. Pas d'exception. Toute variable est le nom lié à la valeur de référence. Toujours.
Vous pouvez penser à une valeur de référence, comme l'adresse de l'objet cible. L'adresse est automatiquement déréférencé. De cette façon, en travaillant avec la valeur de référence, il semble que vous travaillez directement avec l'objet cible. Mais il y a toujours une référence entre les deux, un pas de plus pour passer à la cible.
Voici l'exemple qui prouve que Python utilise le passage par référence:
Si l'argument est passé par valeur, à l'extérieur
lst
ne peut pas être modifiée. Le vert sont les objets cibles (le noir est la valeur stockée à l'intérieur, le rouge est le type d'objet), le jaune est la mémoire avec la valeur de référence à l'intérieur, tirés comme la flèche. Le bleu solide flèche correspond à la valeur de référence a été passé à la fonction (par l'intermédiaire de la flèche bleue en pointillés). Le vilain jaune foncé est le dictionnaire interne. (En fait, il pourrait être attiré comme une ellipse verte. La couleur et la forme ne dit qu'il est interne.)Vous pouvez utiliser le
id()
fonction intégrée d'apprendre ce que la valeur de référence (c'est l'adresse de l'objet cible).Dans les langages compilés, une variable est un espace de mémoire qui est capable de capturer la valeur du type. En Python, une variable est un nom (capturé en interne comme une chaîne de caractères) lié à la référence de la variable qui contient la valeur de référence vers l'objet cible. Le nom de la variable est la clé dans le dictionnaire interne, la valeur de la partie de l'article de dictionnaire des magasins de la valeur de référence de la cible.
Valeurs de référence sont cachés dans Python. Il n'y a pas de manière explicite le type d'utilisateur pour le stockage de la valeur de référence. Toutefois, vous pouvez utiliser un élément de la liste (ou d'un élément dans tout autre type de conteneur) comme variable de référence, parce que tous les conteneurs ne stocker les éléments que les références à des objets cibles. En d'autres termes, les éléments ne sont pas réellement contenue à l'intérieur du conteneur -- uniquement les références aux éléments.
Inventer une nouvelle terminologie (comme le "passage par valeur de référence" ou "appeler par objet" n'est pas utile). "Appeler par (valeur|de référence|nom)" sont les termes standards. "de référence" est un terme. En passant références en valeur décrit avec précision le comportement de Python, Java, et une foule d'autres langues, à l'aide de la terminologie standard.
Le problème est que variable Python n'a pas la même terminologie sens comme dans d'autres langues. De cette façon, appel par référence ne convient pas bien ici. Aussi, comment voulez-vous exactement permet de définir le terme de référence? De manière informelle, la façon Python pourrait facilement être décrit comme en passant l'adresse de l'objet. Mais il ne correspond pas à une potentiellement distribués mise en œuvre de Python.
J'aime cette réponse, mais vous pourriez envisager si l'exemple est vraiment d'aider ou de nuire à l'écoulement. Aussi, si vous avez remplacé la "valeur de référence" par "la référence d'objet' vous seriez en utilisant la terminologie que l'on pouvait considérer "officiels", comme on le voit ici: la Définition de Fonctions
Il y a une note en bas de page indiqué à la fin de cette citation, qui se lit comme suit: "en Fait, appel par référence d'objet serait une meilleure description, car si un objet mutable est passé, l'appelant ne voir aucun changement le destinataire de l'appel fait à elle..." je suis d'accord avec vous que la confusion est causée par essayer de s'adapter à la terminologie établie avec d'autres langues. La sémantique de côté, les choses doivent être comprises sont: dictionnaires / espaces de noms, nom des opérations de liaison et de la relation du nom→pointeur d'objet→(comme vous le savez déjà).
OriginalL'auteur pepr
Un truc tout simple que j'utilise habituellement est de les envelopper dans une liste:
(Ouais, je sais que cela peut être gênant, mais il est parfois assez simple de faire cela.)
Nice. Passer par ref, enveloppez-la dans des [].
OriginalL'auteur AmanicA
(modifier - Blair a mis à jour sa très populaire réponse de sorte qu'il est maintenant exacte)
Je pense qu'il est important de noter que le courant post avec le plus de votes (par Blair Conrad), tout en étant correcte par rapport à son résultat, est trompeuse et est à la limite incorrecte repose sur ses définitions. Bien qu'il existe de nombreux langages (comme C) qui permettent à l'utilisateur de passer soit par référence ou le passage par valeur, Python n'est pas l'un d'eux.
David Cournapeau la réponse de points à la réponse réelle et explique pourquoi le comportement de Blair Conrad post semble être correct, tandis que les définitions ne sont pas.
Dans la mesure où Python est le passage par valeur, toutes les langues sont le passage par valeur depuis quelques morceau de données (que ce soit une "valeur" ou "de référence") doit être envoyé. Toutefois, cela ne signifie pas que Python est le passage par valeur dans le sens où un programmeur C pensons de lui.
Si vous voulez le comportement, Blair Conrad réponse est fine. Mais si vous voulez savoir les écrous et les boulons de pourquoi Python est ni le passage par valeur ou passage par référence, lire David Cournapeau de réponse.
void swap(int& x, int& y) { int temp = x; x = y; y = temp; }
échange les variables passées. En Pascal, vous utilisezvar
au lieu de&
.Je pensais que j'avais répondu à cela il y a longtemps mais je ne le vois pas. Pour l'intégralité - cayhorstmann mal compris ma réponse. Je n'étais pas dire que tout ce qui est appel par valeur dans les termes que la plupart des gens apprennent d'abord concernant le C / C++. Il fallait simplement que valeur est passée (valeur, nom, pointeur, etc.) et que les termes utilisés dans Blair réponse originale à cette question étaient inexactes.
OriginalL'auteur KobeJohn
Il n'y a pas de variables en Python
La clé de la compréhension de la transmission de paramètres est d'arrêter de penser "variables". Il y a des noms et des objets en Python et ensemble, ils
apparaissent comme des variables, mais il est toujours utile de distinguer les trois.
C'est tout là est à lui. La mutabilité est pas pertinent pour cette question.
Exemple:
Cette lie le nom
a
à un objet de type entier qui contient la valeur 1.Cette lie le nom
b
pour le même objet que le nomx
est actuellement lié à l'.Par la suite, le nom
b
n'a rien à voir avec le nom dex
plus.Voir les sections 3.1 et 4.2 dans le Python 3 de la langue de référence.
Donc dans le code indiqué dans la question, la déclaration
self.Change(self.variable)
lie le nomvar
(dans la portée de la fonctionChange
) à l'objet qui contient la valeur'Original'
et l'affectationvar = 'Changed'
(dans le corps de la fonctionChange
) attribue le même nom nouveau: à un autre objet (qui arrive à tenir une chaîne en tant que bien, mais aurait pu être autre chose).Il peut être choquant, mais il n'est pas stupide. Et je ne pense pas qu'il est source de confusion: Il nous l'espérons ouvre le destinataire de l'esprit pour l'explication qui est à venir et la met dans un "je me demande ce qu'ils ont à la place des variables" attitude. (Oui, votre kilométrage peut varier.)
diriez-vous aussi que le Javascript n'a pas de variables? Ils fonctionnent de la même que Python. Aussi, Java, Ruby, PHP, .... Je pense qu'un meilleur enseignement technique est, "Python variables fonctionnent différemment que C est."
Oui, Java a des variables. Donc, Python, JavaScript, Ruby, PHP, etc. Vous ne diriez pas en Java qui
int
déclare une variable, maisInteger
ne le fait pas. Ils ont tous deux de déclarer les variables. LeInteger
variable est un objet, leint
variable est une primitive. Comme un exemple, vous avez démontré comment vos variables de travail en montranta = 1; b = a; a++ # doesn't modify b
. C'est exactement vrai en Python aussi (à l'aide de+= 1
puisqu'il n'est pas++
en Python)!Je ne vois vraiment pas comment cette réponse pourrait être utile dans la lumière de la question. Aucune solution n'est donnée, que le statut quo de python est récité. Comment pouvez-vous passer un argument, de sorte qu'il peut être changé? La plupart des réponses ici ne donnent pas une solution. Mais celui-ci, nie l'existence de l'évident dans les premières lignes, de sorte qu'il se démarque de la meute. Désolé pour le downvote, mais il vient de me faire un peu fou.
OriginalL'auteur Lutz Prechelt
Vous avez obtenu quelques bonnes réponses ici.
OriginalL'auteur bobobobo
Dans ce cas, la variable intitulée
var
dans la méthodeChange
est attribué une référence àself.variable
, et vous avez immédiatement affecter une chaîne àvar
. Il n'est plus pointant versself.variable
. L'extrait de code suivant montre ce qui se passerait si vous modifiez les données de la structure pointée parvar
etself.variable
, dans ce cas une liste:Je suis sûr que quelqu'un pourrait préciser davantage.
OriginalL'auteur Mike Mazur
Python-passer-par-assignation de schéma n'est pas tout à fait la même qu'en C++de référence des paramètres de l'option, mais il s'avère être très similaire à l'argument de passage de modèle du langage C (et autres) dans la pratique:
et les dictionnaires sont également passés par référence d'objet, qui est similaire à la façon dont C
passe tableaux—pointeurs mutable objets peuvent être modifiés en place dans la fonction,
comme C des tableaux.
OriginalL'auteur ajknzhol
Comme vous pouvez le dire, vous devez avoir un objet mutable, mais laissez-moi vous suggérons de vérifier les variables globales, car ils peuvent vous aider ou même de résoudre ce genre de problème!
http://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
exemple:
OriginalL'auteur Nuno Aniceto
Beaucoup de points de vue dans les réponses ici, mais je pense que d'un point supplémentaire n'est pas clairement mentionné ici explicitement. Citant la documentation python https://docs.python.org/2/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
"En Python, les variables qui ne sont référencés à l'intérieur d'une fonction sont implicitement mondiale. Si une variable est affectée d'une valeur de n'importe où au sein de la fonction du corps, il est supposé pour être un local. Si une variable est jamais assigner une nouvelle valeur à l'intérieur de la fonction, la variable est implicitement local, et vous avez besoin de l'indiquer explicitement que "global".
Bien qu'un peu surprenant au premier abord, un moment de explique cet. D'une part, exigeant mondial pour les variables assignées fournit un bar à l'encontre des effets secondaires indésirables. D'autre part, si le mondial était nécessaire pour que toutes les références globales, vous seriez en utilisant mondiale de tous les temps. Vous devez déclarer comme mondiales chaque référence à une fonction intégrée ou à un composant d'un module importé. Ce désordre à l'encontre de l'utilité de la déclaration mondiale pour l'identification des effets secondaires."
Même lors du passage d'un objet mutable à une fonction cela s'applique toujours. Et m'explique clairement la raison de la différence de comportement entre l'affectation de l'objet et de l'exploitation sur l'objet dans la fonction.
donne:
L'affectation à une variable globale qui n'est pas déclaré mondiale crée donc un nouvel objet local et rompt le lien à l'objet original.
OriginalL'auteur Joop
Ici est simple (je l'espère) une explication de la notion
pass by object
utilisé en Python.Chaque fois que vous passez un objet à la fonction, l'objet lui-même est passé (objet en Python est en fait ce que vous appelleriez une valeur dans d'autres langages de programmation) pas la référence à cet objet. En d'autres mots, lorsque vous composez le:
L'objet réel de [0, 1] (ce qui serait appelé une valeur dans d'autres langages de programmation) est passée. Donc, en fait, la fonction
change_me
va essayer de faire quelque chose comme:qui ne sera évidemment pas de modifier l'objet passé à la fonction. Si la fonction ressemblait à ceci:
L'appel dans
qui, évidemment, va changer l'objet. Cette réponse l'explique bien.
list = [1, 2, 3]
causes de réutiliser lelist
nom pour autre chose et oublier l'origine de l'objet. Cependant, vous pouvez essayer delist[:] = [1, 2, 3]
(par la voie delist
est faux nom pour une variable. La réflexion sur[0, 1] = [1, 2, 3]
est un non-sens complet. De toute façon, que pensez-vous des moyens de l'objet lui-même est adopté? Ce qui est copié à la fonction, à votre avis?les objets ne sont pas des littéraux. Ils sont des objets. La seule façon d'en parler est de leur donner quelques noms. C'est pourquoi il est si simple une fois que vous saisir, mais extrêmement compliqué à expliquer. 🙂
Je suis conscient de cela. De toute façon, la liste littérale est converti à l'objet de la liste. En fait, tout objet en Python peut exister sans un nom, et il peut être utilisé même lorsqu'il n'est pas donné à n'importe quel nom. Et vous pouvez penser à eux comme sur des objets anonymes. Pensez à des objets étant les éléments d'une liste. Ils n'ont pas besoin d'un nom. Vous pouvez y accéder par le biais de l'indexation ou d'une itération dans la liste. De toute façon, j'insiste sur
[0, 1] = [1, 2, 3]
est tout simplement un mauvais exemple. Il n'en est rien en Python.Je ne veux pas dire nécessairement Python-définition des noms, que de simples noms. Bien sûr
alist[2]
compte comme un nom d'un troisième élément de l'accédez à la liste. Mais je pense que j'ai mal compris ce que votre problème a été. 🙂Argh. Mon anglais est évidemment beaucoup pire que mon Python. 🙂 Je vais essayer juste une fois de plus. J'ai juste dit que vous devez donner l'objet de quelques noms pour parler d'eux. Par que "les noms de" je ne voulais pas dire "noms définis par Python". Je sais Python mécanismes, ne vous inquiétez pas.
OriginalL'auteur matino
En dehors de toutes les grandes explications sur comment ça fonctionne en Python, je ne vois pas une simple suggestion pour le problème. Comme vous semblez le faire créer des objets et des instances, la pythonic de manipulation des variables d'instance, et la modification est la suivante:
Dans les méthodes d'instance, vous normalement, reportez-vous à
self
pour accéder aux attributs d'instance. Il est normal pour définir les attributs d'instance dans__init__
et de les lire ou de les changer dans les méthodes d'instance. C'est aussi pourquoi vous passezself
la sla, le premier argumentdef Change
.Une autre solution serait de créer une méthode statique comme ceci:
OriginalL'auteur Dolf Andringa
Il existe une petite astuce pour passer un objet par référence, même si la langue n'est pas possible. Il fonctionne en Java aussi, c'est la liste avec un seul élément. 😉
C'est un vilain hack, mais il fonctionne. ;-P
p
est une référence à une mutable liste d'objet qui stocke l'objetobj
. La référence "p", est adoptée enchangeRef
. À l'intérieur dechangeRef
, une nouvelle référence est créée (la nouvelle référence est appeléref
) qui pointe vers la même liste d'objet quep
points. Mais parce que les listes sont mutables, les changements à la liste sont visibles par références. Dans ce cas, vous avez utilisé leref
de référence pour le changement de l'objet à l'index 0 de sorte que par la suite, il stocke lesPassByReference('Michael')
objet. La modification de l'objet de la liste a été faite en utilisantref
mais ce changement n'est visible àp
.Alors maintenant, les références
p
etref
point à une liste d'objet qui stocke l'objet unique,PassByReference('Michael')
. Il s'ensuit donc quep[0].name
retourneMichael
. Bien sûr,ref
a maintenant disparu de la portée et peut être nettoyée mais tout de même.Vous avez pas changé le privé variable d'instance,
name
, de l'originalPassByReference
objet associé à la référenceobj
, cependant. En fait,obj.name
sera de retourPeter
. Ladite commentaires suppose la définitionMark Ransom
a donné.Point étant, je ne suis pas d'accord que c'est un hack (qui, pour moi, signifie se référer à quelque chose qui fonctionne, mais pour des raisons inconnues, non vérifiées ou non par le maître d'œuvre). Il vous suffit de remplacer le
PassByReference
objet avec un autrePassByReference
objet dans votre liste et visées à la dernière des deux objets.OriginalL'auteur itmuckel
J'ai utilisé la méthode suivante pour convertir rapidement un couple de Fortran codes de Python. Vrai, c'est de ne pas passer par référence que la question initiale a été posée, mais c'est un travail simple dans certains cas.
OriginalL'auteur Brad Porter
Tout passage par référence est rien qui s'inscrit bien dans python et devrait être rarement utilisé il y a quelques solutions de contournement qui peut effectivement travailler pour obtenir l'objet actuellement affectée à une variable locale ou même de réaffecter une variable locale à partir de l'intérieur d'une fonction appelée.
L'idée de base est d'avoir une fonction qui peut faire que l'accès et peuvent être transmis en tant qu'objet dans d'autres fonctions ou stockées dans une classe.
Une façon est d'utiliser
global
(pour les variables globales) ounonlocal
(pour les variables locales à une fonction) dans une fonction wrapper.La même idée fonctionne pour la lecture et l'
del
eting une variable.Juste pour la lecture il y a même une façon plus simple de simplement en utilisant
lambda: x
qui retourne un objet appelable que lorsqu'il est appelé retourne la valeur courante de x. C'est un peu comme "appeler par leur nom", utilisé dans des langues dans le passé lointain.Passage 3 wrappers pour accéder à une variable est un peu lourd donc, ceux qui peuvent être enroulés dans une classe qui a un attribut proxy:
Pythons "réflexion" rend-il possible d'obtenir un objet qui est capable de réaffectation d'un nom de variable dans une étendue donnée, sans définir les fonctions explicitement portée:
Ici la
ByRef
classe encapsule un dictionnaire d'accès. Si l'attribut de l'accès àwrapped
est traduite en un point d'accès dans le passé dictionnaire. En passant le résultat de la builtinlocals
et le nom d'une variable locale il finit par accéder à une variable locale. La documentation python que de 3,5 conseille de changer le dictionnaire peut ne pas fonctionner, mais il semble fonctionner pour moi.OriginalL'auteur textshell
compte tenu de la façon python gère des valeurs et des références pour eux, la seule façon vous pouvez faire référence à un arbitraire instance attribut par son nom:
dans le code réel, vous, bien sûr, ajouter la vérification des erreurs sur le dict de recherche.
OriginalL'auteur mARK bLOORE
Depuis votre exemple, il arrive à être orientée objet, vous pouvez apporter la modification suivante à atteindre un résultat similaire:
OriginalL'auteur Jesse Hogan
Par Référence en Python est tout à fait différente de la notion de passage par référence en C++/Java.
Python est “passe-par-objet de référence”, dont il est souvent dit: “les références de l'Objet sont passés par valeur.”[Lire ici]Un. À la fois l'appelant et la fonction se référer au même objet, mais le paramètre de la fonction est une nouvelle variable qui est juste en maintenant une copie de l'objet en l'appelant. Comme C++, un paramètre peut être modifié ou non, en fonction dépend du type de l'objet passé. par exemple; Un immuable type d'objet ne peut pas être modifié dans la fonction appelée alors qu'un objet mutable peuvent être mises à jour ou ré-initialisé. Une différence cruciale entre la mise à jour ou ré-affectation/re-initialisation de la mutable variable est mise à jour de la valeur est renvoyée dans la fonction appelée alors que la réinitialisation de la valeur n'est pas. La portée de la cession de nouveau l'objet d'une mutable variable est locale à la fonction en python. Les exemples fournis par @blair-conrad sont grands pour comprendre cela.
OriginalL'auteur Alok Garg
Vous pouvez simplement utiliser une classe vide comme un exemple pour stocker des objets de référence, car en interne, les attributs de l'objet sont stockées dans une instance dictionnaire. Voir l'exemple.
OriginalL'auteur sergzach