Débutant Python => Passage de paramètre

Débutant Python => Passage de paramètre - Python - Programmation

Marsh Posté le 01-10-2007 à 18:22:48    

Salut à tous, je débute en Python et je me pose certaines questions à propos du passage de paramètres à une fonction. Par adresse ou par valeur ???
 
Exemple 1

Code :
  1. def toto(x):
  2.    x=5
  3. a=0
  4. print a       => 0 - ok
  5. toto(a)
  6. print a       => Toujours 0 - ok, cela a été passé par valeur


 
Exemple 2

Code :
  1. def toto(x):
  2.    x[0]=5
  3. a=range(10)
  4. print a[0]     => 0 - ok
  5. toto(a)
  6. print a[0]     => Là j'ai 5 - ok, la fonction "toto" a reçu l'adresse de mon tableau et a pu le modifier


 
Donc il semble que si on passe à une fonction un truc simple (style un int) le passage se fait par valeur, si on lui passe un truc complexe (un tableau, un objet) le passage se fait par adresse et la fonction peut modifier le truc reçu. Me trompe-je ???
 
Question subsidiaire => il y a moyen dans l'exemple 1 de faire en sorte que toto() modifie le paramètre reçu ???
 
Merci à tous


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 01-10-2007 à 18:22:48   

Reply

Marsh Posté le 01-10-2007 à 19:14:10    

par adresse.
 
dans ton exemple1, tu ecrase l'adresse de ton 'ancien' x.
 
l'effet est surtout visible sur les paramètres par défaut :  
 

Code :
  1. def stuff ( x = 3 ):
  2.      print x
  3. stuff( x = 5)
  4. stuff()


la sortie devrait être

Code :
  1. 5
  2. 5


---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 01-10-2007 à 19:35:53    

zapan666 a écrit :

par adresse.
 
dans ton exemple1, tu ecrase l'adresse de ton 'ancien' x.


 
Ok. Et il y a moyen de modifier le contenu de ce "x" et non son adresse (si on imagine que la valeur est calculée par la fonction et donc qu'on ne peut pas la passer lors de l'appel à toto) ???
Python c'est extra mais quand on vient du C on aime bien savoir ce qu'il se passe au fond des choses...

Message cité 1 fois
Message édité par Sve@r le 01-10-2007 à 19:37:56

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 01-10-2007 à 21:33:08    

Python est comme java, il fonctionne par "passage de références par valeur".
 
Une "variable" comme "x" n'est en fait qu'un label, un pointeur vers une référence Python.
 
Donc "x = 5" donne simplement le label "x" à la référence vers l'objet de valeur "5"

zapan666 a écrit :

par adresse.
 
dans ton exemple1, tu ecrase l'adresse de ton 'ancien' x.
 
l'effet est surtout visible sur les paramètres par défaut :  
 

Code :
  1. def stuff ( x = 3 ):
  2.      print x
  3. stuff( x = 5)
  4. stuff()


la sortie devrait être

Code :
  1. 5
  2. 5



non et non, et ça sort 5 et 3.
 
Ce dont tu parles, c'est le fait que le paramètre par défaut est construit une fois pour toute (quand la fonction est générée), donc quand çe paramètre est mutable ça fait des effets bizarres, les gens découvrent habituellement ça en utilisant des listes, quand ils modifient l'objet référencé:

Code :
  1. >>> def foo(bar=5):
  2.     print bar
  3.  
  4.     
  5. >>> foo()
  6. 5
  7. >>> foo(12)
  8. 12
  9. >>> foo(bar=12)
  10. 12
  11. >>> foo()
  12. 5
  13. >>> def bar(baz=[]):
  14.     print baz
  15.  
  16.     
  17. >>> bar()
  18. []
  19. >>> bar([1,2,3,4])
  20. [1, 2, 3, 4]
  21. >>> bar()
  22. []
  23. >>> def bar(baz=[]):
  24.     baz.append(random.randint(0,9))
  25.     return baz
  26.  
  27. >>> bar()
  28. [1]
  29. >>> bar()
  30. [1, 1]
  31. >>> bar()
  32. [1, 1, 5]
  33. >>> bar()
  34. [1, 1, 5, 5]
  35. >>> bar([])
  36. [4]
  37. >>> bar([5,1])
  38. [5, 1, 6]
  39. >>> bar()
  40. [1, 1, 5, 5, 7]
  41. >>>


Sve@r a écrit :

Ok. Et il y a moyen de modifier le contenu de ce "x" et non son adresse (si on imagine que la valeur est calculée par la fonction et donc qu'on ne peut pas la passer lors de l'appel à toto) ???


x n'est pas un conteneur, c'est un label vers une référence.
 
Ca ne correspond ni a un pointeur C ni a une référence C++ (surtout pas même)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 01-10-2007 à 22:59:44    

masklinn a écrit :


Code :
  1. >>> def bar(baz=[]):
  2.     baz.append(random.randint(0,9))
  3.     return baz
  4.  
  5. >>> bar()
  6. [1]
  7. >>> bar()
  8. [1, 1]
  9. >>> bar()
  10. [1, 1, 5]
  11. >>> bar()
  12. [1, 1, 5, 5]
  13. >>> bar([])
  14. [4]
  15. >>> bar([5,1])
  16. [5, 1, 6]
  17. >>> bar()
  18. [1, 1, 5, 5, 7]
  19. >>>



Excellent exemple très démonstratif.   :bounce:  
Si je ne me trompe pas, il montre l'existence d'une variable spécifique au paramètre par défaut et s'il n'y a pas de paramètre, c'est cette variable qui est utilisée (d'où le fait qu'on retrouve les nombres déjà générés quand on appelle bar() sans paramètre même si on a appelé bar() avec des paramètres entre temps)
 

masklinn a écrit :


x n'est pas un conteneur, c'est un label vers une référence.
 
Ca ne correspond ni a un pointeur C ni a une référence C++ (surtout pas même)


Ok donc on peut pas. Bon, c'est pas grave et de toute façon je suis certain que si un jour j'ai besoin que ma fonction modifie une variable, je pourrai me débrouiller autrement. C'était juste pour savoir.
 
Merci  :hello:
 
PS: Mercredi, jeudi et vendredi je suis en stage Python intensif chez Bull (Massy Palaiseau). Je vais m'éclater    :love:

Message cité 1 fois
Message édité par Sve@r le 01-10-2007 à 23:01:36

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 02-10-2007 à 08:01:36    

Sve@r a écrit :


Excellent exemple très démonstratif.   :bounce:  
Si je ne me trompe pas, il montre l'existence d'une variable spécifique au paramètre par défaut et s'il n'y a pas de paramètre, c'est cette variable qui est utilisée


Pas variable :fou:
 
Objet :fou:
 
Objet spécifique par défaut instancié au moment de la création (de l'instanciation) de la fonction, même :o
 
Sinon, oui.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-10-2007 à 09:21:52    

masklinn a écrit :


non et non, et ça sort 5 et 3.


oups :D


---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 03-10-2007 à 11:04:58    

masklinn a écrit :


Objet spécifique par défaut instancié au moment de la création (de l'instanciation) de la fonction, même :o


 
J'ai développé cet exemple et créé une méthode avec paramètre par défaut identique à la fonction bar()

Code :
  1. class cTest():
  2.    def bar(self, tab=[]):
  3.        tab.append(random.randint(0,9))
  4.        return tab
  5. v1=cTest()
  6. v2=cTest()
  7. tab1=v1.bar()
  8. print tab1    => [0]
  9. tab1=v1.bar()
  10. print tab1    => [0, 7]
  11. tab1=v1.bar()
  12. print tab1    => [0, 7, 4]
  13. tab2=v2.bar()
  14. print tab2    => [0, 7, 4, 4]


 
Ainsi, on peut s'apercevoir que cet objet instancié lors de l'appel de la méthode "bar" est commun à tous les objets "cTest" créés...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 03-10-2007 à 11:07:00    

Ben oui, puisque la fonction "bar" est instanciée en même temps que la classe "cTest". Si c'était pas le cas, les gros objets un peu lourdingues seraient inutilisables (parce que leur instanciation signifieraient créer et initialiser toutes leurs méthodes et propriétés... un peu violent)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed