web-dev-qa-db-fra.com

Python affectation de référence de variable

Dans le code

y = 7
x = y    
x = 8

Maintenant, y sera 7 et x sera 8. Mais en fait, je veux changer y. Puis-je attribuer la référence de y et le faire?

Par exemple, en C++, la même chose peut être obtenue que,

int y = 8;
int &x = y;
x = 9;

Maintenant, y et x seront tous les 9

39
viji

Non tu ne peux pas. Comme le soulignent d'autres réponses, vous pouvez (ab?) Utiliser l'aliasing d'objets mutables pour obtenir un effet similaire. Cependant, ce n'est pas la même chose que les références C++, et je veux expliquer ce qui se passe réellement pour éviter toute idée fausse.

Vous voyez, en C++ (et dans d'autres langages), une variable (et les champs d'objet et les entrées dans les collections, etc.) est un emplacement de stockage et vous écrivez une valeur (par exemple, un entier, un objet ou un pointeur) dans cet endroit. Dans ce modèle, les références sont un alias pour un emplacement de stockage (de tout type) - lorsque vous attribuez à une variable non-référence, vous copiez une valeur (même si ce n'est qu'un pointeur, c'est toujours une valeur) vers l'emplacement de stockage; lorsque vous attribuez à une référence, vous copiez vers un emplacement de stockage ailleurs. Notez que vous ne pouvez pas modifier une référence elle-même - une fois qu'elle est liée (et elle doit dès que vous en créez une), toutes les affectations qui lui sont affectées ne modifient pas la référence mais tout ce qui est référencé.

Dans Python (et autres langages), une variable (et les champs d'objet, et les entrées dans les collections, etc.) est juste un nom. Les valeurs sont quelque part else ( par exemple saupoudré partout dans le tas), et une variable fait référence (pas dans le sens des références C++, plus comme un pointeur moins l'arithmétique du pointeur) à une valeur. Plusieurs noms peuvent faire référence à la même valeur (ce qui est généralement une bonne chose) . Python (et d'autres langages) appelle tout ce qui est nécessaire pour faire référence à une valeur une référence, bien qu'il ne soit pas du tout lié à des choses comme les références C++ et le passage par référence. Affectation à une variable (ou champ objet, ou ...) fait simplement référence à une autre valeur. Le modèle entier des emplacements de stockage ne s'applique pas à Python, le programmeur ne gère jamais les emplacements de stockage pour les valeurs. Tout ce qu'il stocke et mélange est Python références, et ce ne sont pas des valeurs en Python, elles ne peuvent donc pas être la cible d'autres Python références.

Tout cela est indépendant de la mutabilité de la valeur - c'est la même chose pour les entiers et les listes, par exemple. Vous ne pouvez pas prendre une variable qui fait référence à l'un ou l'autre et écraser l'objet vers lequel il pointe. Vous pouvez seulement dire à l'objet de modifier des parties de lui-même - par exemple, changer une référence qu'il contient.

Est-ce un modèle plus restrictif? Peut-être, mais c'est assez puissant la plupart du temps. Et quand ce n'est pas le cas, vous pouvez le contourner, soit avec une classe personnalisée comme celle donnée ci-dessous, ou (équivalente, mais moins évidente) une collection à élément unique.

class Reference:
    def __init__(self, val):
        self._value = val # just refers to val, no copy

    def get(self):
        return self._value

    def set(self, val):
        self._value = val

Cela ne vous permettra toujours pas d'alias une variable ou un champ objet "normal", mais vous pouvez avoir plusieurs variables faisant référence au même objet Reference (idem pour l'alternative mutable-singleton-collection). Il suffit de faire attention à toujours utiliser .get()/.set() (ou [0]).

53
user395760

Non, Python n'a pas cette fonctionnalité.

Si vous aviez une liste (ou tout autre objet modifiable), vous pourriez faire ce que vous voulez en mutant l'objet auquel x et y sont liés:

>>> x = [7]
>>> y = x
>>> y[0] = 8
>>> print x
[8]

Voyez-le travailler en ligne: ideone

16
Mark Byers

Vous devez utiliser un objet mutable pour cela.

Dans python x & y ne sont que des références à des objets donc y = 7 signifie que y pointe vers l'objet 7. x=y signifie x pointe également vers 7, mais comme 7 est immuable, donc changer la valeur de x change simplement l'objet 7 et y pointe toujours vers 7.

>>> y = [7]
>>> x = y
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7]
>>> y
[8]
5
Ashwini Chaudhary

Alternativement, vous pouvez utiliser un conteneur auto-fabriqué.

class Value(object):
    def __init__(self, value): self.value = value

y = Value(7)
x = y
x.value = 8
print y.value

idéone

3
glglgl