136 votes

Passage d'un entier par référence en Python

Comment puis-je passer un entier par référence en Python ?

Je veux modifier la valeur d'une variable que je passe à la fonction. J'ai lu que tout en Python est transmis par valeur, mais il doit y avoir un truc facile. Par exemple, en Java, vous pouvez passer les types de référence de Integer , Long etc.

  1. Comment puis-je passer un entier dans une fonction par référence ?
  2. Quelles sont les meilleures pratiques ?

155voto

mgilson Points 92954

Cela ne fonctionne pas tout à fait de cette manière en Python. Python transmet des références à des objets. Dans votre fonction, vous avez un objet -- Vous êtes libre de muter cet objet (si possible). Cependant, les entiers sont immuable . Une solution de contournement consiste à passer l'entier dans un conteneur qui peut être muté :

def change(x):
    x[0] = 3

x = [1]
change(x)
print x

Au mieux, c'est moche et maladroit, mais vous ne ferez pas mieux en Python. La raison en est qu'en Python, l'affectation ( = ) prend l'objet qui est le résultat du côté droit et le lie à ce qui est du côté gauche *(ou le passe à la fonction appropriée).

En comprenant cela, nous pouvons voir pourquoi il n'y a aucun moyen de changer la valeur d'un objet immuable à l'intérieur d'une fonction -- vous ne pouvez changer aucun de ses attributs parce qu'il est immuable, et vous ne pouvez pas simplement assigner une nouvelle valeur à la "variable" parce qu'alors vous créez réellement un nouvel objet (qui est distinct de l'ancien) et lui donnez le nom que l'ancien objet avait dans l'espace de noms local.

En général, la solution de contournement consiste simplement à retourner l'objet que vous voulez :

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

*Dans le premier exemple de cas ci-dessus, 3 est en fait transmis à x.__setitem__ .

35voto

Gabe Points 49718

La plupart des cas où vous devez passer par référence sont ceux où vous devez renvoyer plus d'une valeur à l'appelant. Une "meilleure pratique" consiste à utiliser plusieurs valeurs de retour, ce qui est beaucoup plus facile à faire en Python que dans des langages comme Java.

Voici un exemple simple :

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

18voto

Uri Points 2724

Il ne s'agit pas exactement de transmettre une valeur directement, mais de l'utiliser comme si elle était transmise.

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

Mises en garde :

  • nonlocal a été introduit dans python 3
  • Si la portée englobante est la portée globale, utilisez global au lieu de nonlocal .

12voto

Sergey Kovalev Points 193

Ce n'est peut-être pas une méthode pythique, mais vous pouvez faire ceci

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

9voto

abarnert Points 94246

En réalité, la meilleure pratique consiste à prendre du recul et à se demander si vous avez vraiment besoin de faire cela. Pourquoi vous voulez modifier la valeur d'une variable que vous passez à la fonction ?

Si vous avez besoin de le faire pour un hack rapide, le moyen le plus rapide est de passer un list en tenant l'entier, et collez un [0] autour de chaque utilisation, comme le démontre la réponse de mgilson.

Si vous devez le faire pour quelque chose de plus important, écrivez une class qui a un int en tant qu'attribut, de sorte que vous pouvez simplement le définir. Bien entendu, cela vous oblige à trouver un bon nom pour la classe et pour l'attribut - si vous ne trouvez rien, relisez la phrase plusieurs fois, puis utilisez la fonction list .

Plus généralement, si vous essayez de porter un idiome Java directement en Python, vous vous y prenez mal. Même lorsqu'il y a une correspondance directe (comme dans le cas de static / @staticmethod ), vous ne voulez toujours pas l'utiliser dans la plupart des programmes Python juste parce que vous l'utiliseriez en Java.

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