Partage
  • Partager sur Facebook
  • Partager sur Twitter

Fonction qui retourne un résultat sans s'arrêter?

Sujet résolu
    25 mai 2015 à 22:16:43

    Bonsoir,

    J'aimerai créer une fonction qui retourne un résultat arrivé à un certain stade du calcul, par exemple:

    def fonction ():

      u = []

        for t in xrange (100):

          #Partie calculatoire

           if (t)%10 == 0:

           return u           <------


      return u


    Comme ça lorsque je fais appel à la fonction en entrant "u=fonction()", je vois le résultat du calcul s'afficher en continue. Le soucis ici c'est que return arrête complètement le calcul et sort de la fonction; n'y aurait-il pas alors une solution pour le continuer?

    -
    Edité par Jarka 25 mai 2015 à 22:18:06

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      25 mai 2015 à 22:25:43

      Renseigne-toi sur les générateurs et le mot-clé yield.

      • Partager sur Facebook
      • Partager sur Twitter
        25 mai 2015 à 22:38:00

        J'ai remplacé 'return' par 'yield', mais dès la 1ère itération ça me sort: "ValueError: too many values to unpack". C'est du au fait que le calcul à faire est fastidieux?

        De plus, je n'ai plus le droit de mettre "return" en fin de fonction du coup non plus :o

        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          25 mai 2015 à 22:58:56

          Jarkamit a écrit:

          J'ai remplacé 'return' par 'yield', mais dès la 1ère itération ça me sort: "ValueError: too many values to unpack". C'est du au fait que le calcul à faire est fastidieux?

          De plus, je n'ai plus le droit de mettre "return" en fin de fonction du coup non plus :o


          Google translate -> 'Too many values to unpack' -> 'Trop de valeurs pour décompresser'. Tu en déduis donc qu'à la ligne n°... (c'est la ligne où tu appelle ta fonction), le programme à trop de valeurs à décompresser, donc que ta fonction renvoie trop de valeurs.

          Sinon, pour le mot clé yield je te propose Google -> 'yield python' -> 1er, second, et troisième lien.

          Et non, tu n'as pas le droit de mélanger 'return' et 'yield' dans une seule fonction.
          • Partager sur Facebook
          • Partager sur Twitter
            25 mai 2015 à 23:04:22

            Nelimee a écrit:

            Jarkamit a écrit:

            J'ai remplacé 'return' par 'yield', mais dès la 1ère itération ça me sort: "ValueError: too many values to unpack". C'est du au fait que le calcul à faire est fastidieux?

            De plus, je n'ai plus le droit de mettre "return" en fin de fonction du coup non plus :o


            Google translate -> 'Too many values to unpack' -> 'Trop de valeurs pour décompresser'. Tu en déduis donc qu'à la ligne n°... (c'est la ligne où tu appelle ta fonction), le programme à trop de valeurs à décompresser, donc que ta fonction renvoie trop de valeurs.

            Et du coup je ne peux pas l'utiliser le 'yield'? :(

            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              25 mai 2015 à 23:28:35

              Le problème ne vient pas de yield. Voici un exemple de code qui va renvoyer la même erreur:

              In [7]: def f(x):
                 ...:     return x, x**2, x**3
                 ...: 
              
              In [8]: u = f(3)
              
              In [9]: print(u, type(u))
              (3, 9, 27) <class 'tuple'>
              
              In [10]: u, v, w = f(3)
              
              In [11]: print(u, type(u), v, type(v), w, type(w))
              3 <class 'int'> 9 <class 'int'> 27 <class 'int'>
              
              In [12]: u, v = f(3)
              ---------------------------------------------------------------------------
              ValueError                                Traceback (most recent call last)
              <ipython-input-12-91c2efb2d8c2> in <module>()
              ----> 1 u, v = f(3)
              
              ValueError: too many values to unpack (expected 2)
              

              Ici le premier test est bon, u est un tuple contenant 3 valeurs, il n'y a pas de problème.

              Le second test est toujours bon, parce que Python comprends qu'il faut 'identifier' les 3 valeurs du tuple retourné par f(3) avec les 3 variables u, v, et w.

              Le troisième test ne marche pas, parce que Python ne comprends pas comment il peut faire rentrer 3 valeurs dans 2 variables. Et d'ailleurs, toi non plus tu ne sais sûrement pas comment faire. Comment Python peut-il deviner si tu veux:

              • Seulement les 2 premières valeurs, et la troisième tu t'en fiche (donc u=3, v=9, et la dernière valeur est 'à jeter')
              • Les trois valeurs, u est un tuple et v un int: u = (3, 9) et v = 27
              • Les trois valeurs, u est un int et v un tuple: u = 3 et v = (9, 27)

              Donc tu as sûrement un problème dans le genre (un nombre de variables à gauche qui ne correspond pas au nombre de valeurs retournées par la fonction).

              • Partager sur Facebook
              • Partager sur Twitter
                26 mai 2015 à 0:01:48

                J'ai vérifié et je ne pense pas que mon problème vienne de ça, de plus ça fonctionnait parfaitement lorsqu'il y'avait le "return" à la place du "yield".

                En passant, regarde tes messages s-il te plaît ^^

                -
                Edité par Jarka 26 mai 2015 à 0:02:23

                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  26 mai 2015 à 6:08:26

                  Poste ton code exact et le traceback complet :)

                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 mai 2015 à 13:13:48

                    Salut,

                    Quand tu utilise yield, l'appel de la fonction ne va pas renvoyer directement le résultat. Ça va juste instancier le générateur. Autrement dit, si tu fais:

                    def fonction():
                        u = 1
                        v = 2
                        return u, v
                    
                    #Ça fonctionne
                    u, v = fonction()
                    
                    
                    #Mais avec un générateur non
                    def fonction():
                        u = 1
                        v = 2
                        yield u, v
                    
                    #Ça ne fonctionne plus:
                    u, v = fonction()  #car ici fonction initialise le générateur
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Précepte: Le mieux est l'ennemi du bien
                      26 mai 2015 à 15:29:28

                      Merci pour vos réponses, mais plus concrètement voici mon code:

                      def fonction (Nx,Ny,Nt):
                       
                          
                          u = [[3+random()for j in range (Nx)]]
                          v = [[3+random()for j in range (Ny)]]
                          
                          
                          for t in xrange (Nt): 
                              
                              if t %1000 == 0: ############### De là
                                  return (u,v)    ############### Jusqu'à là
                                  
                                  
                              for x in xrange(Nx):
                                  for y in xrange(Ny):
                                      
                                      
                                      u[x][y] +=u[x][y]+(u[x][y]**(1/2)
                                      v[x][y] +=u[x][y]-(u[x][y]**(1/2)
                                         
                          
                          return (u,v)

                      La partie que j'ai bourré de "#####" est celle qui qui correspond à l'endroit qui devrait normalement me permettre d'obtenir les résultats de mes calculs au fur et à mesure de leur avancement. Comme j'ai placé un "return" ça ne fonctionne évidemment pas et j'aimerai que vous me corrigiez cette partie si possible peu importe la manière.

                      Comme ça lorsque je ferais " u,v=fonction (Nx,Ny,Nt)", je pourrais obtenir les résultats en continue. 

                      -
                      Edité par Jarka 26 mai 2015 à 17:50:21

                      • Partager sur Facebook
                      • Partager sur Twitter
                        26 mai 2015 à 15:37:39

                        En utilisant yield, ta fonction retourne maintenant un générateur, et donc s'utilise autrement. Il faut d'abord récupérer le retour puis utiliser next pour accéder aux valeurs yieldées.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          26 mai 2015 à 15:46:21

                          Merci entwanne mais si quelqu'un pouvait mettre tes dires directement en application sur mon code, ça serait vraiment chouette car j'y comprend pas grand chose :euh:

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            26 mai 2015 à 16:20:13

                            Je crois qu'ils n'ont pas envie ;)

                            yield est une fonction avancée python, si tu n'as pas la possibilité de comprendre la documentation, peut-être que tu vas un peu vite dans ton apprentissage.

                            Utilises une liste à la place ?

                            -
                            Edité par Anonyme 26 mai 2015 à 16:21:05

                            • Partager sur Facebook
                            • Partager sur Twitter
                              26 mai 2015 à 16:25:29

                              En fait l'apprentissage de Python n'est pas le but de cette manipulation, c'est pour moi juste un moyen de réaliser une simulation numérique. Après celle-ci, peut-être que je ne retoucherais plus à Python (du moins pas avant un long moment) donc plus vite ça sera réglé, mieux ça sera :pirate:

                              -
                              Edité par Jarka 26 mai 2015 à 16:26:01

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                26 mai 2015 à 16:27:42

                                Et comment veux-tu réaliser quelque chose en Python si tu ne veux pas apprendre Python !? o_O

                                La seule information dont tu avais besoin ici t'a déjà été donné : utilise un générateur.

                                Tu ne sais pas ce qu'est un générateur ? Renseignes-toi (la doc de Python est très bien foutue) ! Tu ne veux pas apprendre Python ? Pourquoi tu fais ton programme avec ? On te l'impose ? Apprend-le...

                                -
                                Edité par Anonyme 26 mai 2015 à 16:36:31

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  26 mai 2015 à 16:34:43

                                  Il y'a "apprendre Python" et "apprendre Python". Pour les travaux que je réalise avec, les connaissances que j'ai déjà me suffisent amplement. :-°
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Anonyme
                                    26 mai 2015 à 16:35:19

                                    Si ce n'est que ça alors voici un exemple

                                    def func():
                                        while True:
                                            yield
                                            
                                    for n in func():
                                        print(n)
                                    



                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      26 mai 2015 à 16:42:00

                                      Merci oldProgrammer mais je ne vois pas du tout comment incorporer ce que tu me proposes dans mon code plus haut, à la place des 2 "return"
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Anonyme
                                        26 mai 2015 à 16:54:10

                                        def fonction (Nx,Ny,Nt):
                                          
                                             
                                            u = [[1+random()for j in range (Nx)]]
                                            v = [[1+random()for j in range (Ny)]]
                                             
                                             
                                            for t in range (Nt):
                                                 
                                                if t %1000 == 0: 
                                                    yield (u,v)
                                                     
                                                     
                                                for x in range(Nx):
                                                    for y in range(Ny):
                                                        xp=(x+1) %Nx    
                                                        xm=x-1
                                                        yp=(y+1) %Ny
                                                        ym=y-1
                                                         
                                                         
                                                        u[x][y] +=u[x][y]+(u[x][y]**2)
                                                        v[x][y] +=u[x][y]-(u[x][y]**2)
                                                            
                                             
                                            yield (u,v)
                                        
                                        for u, v in fonction(.., .., ..): # à compléter
                                            print(u, v)
                                        

                                        Il suffisait juste de remplacer tes return par yield... Le générateur se parcoure comme on parcourt une liste, avec une boucle for toute simple !

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Anonyme
                                          26 mai 2015 à 17:01:14

                                          Jarkamit a écrit:

                                          Il y'a "apprendre Python" et "apprendre Python". Pour les travaux que je réalise avec, les connaissances que j'ai déjà me suffisent amplement. :-°

                                          Ce sujet est la preuve que non. Tu as besoin d'un générateur, mais tu ne veux pas apprendre à en créer. Comment veux-tu que l'on t'aide sans faire le travail à ta place ?

                                          Jarkamit a écrit:

                                          Merci oldProgrammer mais je ne vois pas du tout comment incorporer ce que tu me proposes dans mon code plus haut, à la place des 2 "return"

                                          Qu'est-ce qu'elle est sensés faire cette fonction ? Parce que ce que tu nous montre plus-haut ne fonctionne pas et est incompréhensible en l'état...


                                          Voici le célèbre algorithme de Fibonacci que tout développeur Python connaît obligatoirement, qui sert toujours d'exemple d'utilisation des générateur (et accessoirement pour présenter l'affectation multiple) :

                                          def fibo(n):
                                              a, b = 0, 1
                                              for _ in range(n):
                                                  yield a
                                                  a, b = b, a + b
                                          

                                          Il s'utilise ainsi :

                                          >>> fibo(6)
                                          <generator object="" fibo="" at="">
                                          >>> for n in fibo(6):
                                          ...     print(n)
                                          ...
                                          0
                                          1
                                          1
                                          2
                                          3
                                          5
                                          </generator>
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            26 mai 2015 à 18:02:31

                                            Je m'excuse pour le précédent code, j'avais tenté d’alléger vite fait un code plus long à la base et ça a donné ce truc indigeste, cette fois ci c'est rectifié il marche.

                                            Merci encore Oldprogrammer, mais le "print" en toute fin est gênant car je ne chercher pas à écrire les valeurs de la liste, mais à en créer une image comme tu peux le voir dans le code suivant:

                                            import matplotlib.pyplot as plt
                                            from matplotlib import cm
                                            from random import random
                                            
                                            def fonction (Nx,Ny,Nt):
                                               
                                                  
                                                u = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                v = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                  
                                                  
                                                for t in xrange (Nt): 
                                                    
                                                    if t %10 == 0:
                                                      print(t) 
                                                      #Retourner le résultat ICI
                                                    
                                                    for x in xrange(Nx):
                                                        for y in xrange(Ny):
                                                            
                                                            u[x][y] +=v[x][y]+u[x][y]**(1/2)
                                                            v[x][y] +=u[x][y]-u[x][y]**(1/2)
                                                            
                                                imag=plt.imshow(u,interpolation='nearest',cmap=cm.binary)                 
                                                imag.set_data(v)
                                                imag.autoscale()
                                                plt.draw()
                                                plt.pause(1e-6)
                                                  
                                                return (u,v) 


                                            Je voudrais en fait renvoyer l'image crée au fur et à mesure à chaque fois que j'aurais la condition "T %10 ==0" vérifiée.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              26 mai 2015 à 19:25:10

                                              En reprenant la fonction écrite par oldP:

                                              def fonction (Nx,Ny,Nt):
                                                 
                                                    
                                                  u = [[1+random()for j in range (Nx)]]
                                                  v = [[1+random()for j in range (Ny)]]
                                                    
                                                    
                                                  for t in range (Nt):
                                                        
                                                      if t %1000 == 0:
                                                          yield (u,v)
                                                            
                                                            
                                                      for x in range(Nx):
                                                          for y in range(Ny):
                                                              xp=(x+1) %Nx   
                                                              xm=x-1
                                                              yp=(y+1) %Ny
                                                              ym=y-1
                                                                
                                                                
                                                              u[x][y] +=u[x][y]+(u[x][y]**2)
                                                              v[x][y] +=u[x][y]-(u[x][y]**2)
                                                                   
                                                  yield (u,v)
                                              
                                              
                                              #Enregistrement de u et v dans une liste
                                              lst = []
                                              lst_u = []
                                              lst_v = []
                                              for u, v in fonction(.., .., ..): # à compléter
                                                  lst.append((u, v))
                                                  lst_u.append(u)
                                                  lst_v.append(v)
                                                  #Ou toute autre action que tu souhaites


                                              Edit: In fine pourquoi souhaites-tu récupérer tes informations au fur et à mesure au lieu de les récupérer à la fin?

                                              -
                                              Edité par Olygrim 26 mai 2015 à 19:27:21

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Précepte: Le mieux est l'ennemi du bien
                                                26 mai 2015 à 19:29:04

                                                Jarkamit a écrit:

                                                Merci encore Oldprogrammer, mais le "print" en toute fin est gênant car je ne chercher pas à écrire les valeurs de la liste, mais à en créer une image comme tu peux le voir dans le code suivant:

                                                Si tu ne veux pas du print, tu l'enlèves et tu fais ce que tu veux à la main.

                                                Olygrim> Quel intérêt de mettre les u et v dans des listes alors qu'on peut déjà itérer sur les résultats ?

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  26 mai 2015 à 19:42:46

                                                  @entwanne

                                                  Oui tu as raison. En écrivant je me suis d'ailleurs rendu compte que ça n'avait pas beaucoup d'intérêt.

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Précepte: Le mieux est l'ennemi du bien
                                                    26 mai 2015 à 20:02:11

                                                    Merci Olygram mais je cherche à afficher des images, du coup j'ai essayé ça:

                                                    import matplotlib.pyplot as plt
                                                    from matplotlib import cm
                                                    from random import random
                                                     
                                                    def fonction (Nx,Ny,Nt):
                                                        
                                                           
                                                        u = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                        v = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                           
                                                           
                                                        for t in xrange (Nt):
                                                             
                                                            if t %10 == 0:
                                                              print(t)
                                                              yield(u,v)
                                                             
                                                            for x in xrange(Nx):
                                                                for y in xrange(Ny):
                                                                     
                                                                    u[x][y] +=v[x][y]+u[x][y]**(1/2)
                                                                    v[x][y] +=u[x][y]-u[x][y]**(1/2)
                                                                     
                                                               
                                                        yield (u,v)
                                                    
                                                    for u, v in fonction (100,100,100):
                                                            
                                                        imag=plt.imshow(u,interpolation='nearest',cmap=cm.binary)
                                                        plt.xticks([])
                                                        plt.yticks([])
                                                        imag.set_data(v)
                                                        imag.autoscale()
                                                        plt.draw()

                                                    Mais bizarrement l'image n'est jamais affiché lorsque la condition "t%10==0" est vérifiée; elle ne l'est que lorsque t = Nt (fin de boucle). >_<

                                                    -
                                                    Edité par Jarka 26 mai 2015 à 20:06:41

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      26 mai 2015 à 22:09:16

                                                      Zut alors, dès qu'on touche au but d'un coup y'a plus de réponses :euh:

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        26 mai 2015 à 22:22:49

                                                        Ça fait très longtemps que je n'ai pas utilisé matplotlib, mais es-tu sûr de l'utiliser correctement ?

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Anonyme
                                                          26 mai 2015 à 22:23:52

                                                          Parce-que le problème n'est plus d'ordre syntaxique ! La réflexion ne doit venir que de toi, d'ailleurs, toi seul est censé être impliqué dans ton exercice...
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            26 mai 2015 à 22:38:03

                                                            entwanne a écrit:

                                                            Ça fait très longtemps que je n'ai pas utilisé matplotlib, mais es-tu sûr de l'utiliser correctement ?


                                                            Le code original était celui là:

                                                            import matplotlib.pyplot as plt
                                                            from matplotlib import cm
                                                            from random import random
                                                             
                                                            def fonction (Nx,Ny,Nt):
                                                                
                                                                   
                                                                u = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                                v = [[3+random()for j in range (Ny)] for i in range (Nx)]
                                                                   
                                                                   
                                                                for t in xrange (Nt):  
                                                                    for x in xrange(Nx):
                                                                        for y in xrange(Ny):
                                                                             
                                                                            u[x][y] +=v[x][y]+u[x][y]**(1/2)
                                                                            v[x][y] +=u[x][y]-u[x][y]**(1/2)
                                                                             
                                                                imag=plt.imshow(u,interpolation='nearest',cmap=cm.binary)                
                                                                imag.set_data(v)
                                                                imag.autoscale()
                                                                plt.draw()
                                                                plt.pause(1e-6)
                                                                   
                                                                return (u,v)
                                                            u,v=fonction(100,100,100)

                                                            Et ça fonctionne parfaitement. Et lorsque je l'ai modifié en rajoutant les "yield" dans le code plus haut, ça n'a pas changé de fonctionnement puisque ça continue à me fournir l'image uniquement en fin de boucle.

                                                            oldProgrammer a écrit: 

                                                            Parce-que le problème n'est plus d'ordre syntaxique ! La réflexion ne doit venir que de toi, d'ailleurs, toi seul est censé être impliqué dans ton exercice...

                                                            J'ai fait mon possible. J'ai effectué un tas de combinaisons et perdu beaucoup de temps à faire ça pour rien au final. J'ai de grosses contraintes de temps et la partie simulation numérique ne consiste qu'une minime partie du boulot que je réalise à côté, j'ai vraiment pas du tout le temps de m'aventurer dans une documentation conséquente de Python et rien ne garantit que j'y trouverais ce que je cherche. En plus ca sera surement la dernière fois que j'utilise Python d'ailleurs car je prévois de passer à Matlab ensuite, plus adéquat à mes tâches.

                                                            -
                                                            Edité par Jarka 26 mai 2015 à 22:40:23

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              26 mai 2015 à 23:08:44

                                                              Salut,

                                                              Regarde dans ton code qui "fonctionne", en ligne 23 tu as écrit plt.pause(1e-6). Il te faut aussi cette pause dans l'autre code après le plt.draw().

                                                              Par contre je ne comprends pas ce que tu tentes de dessiner. Car tu places le vecteur u comme image, mais de suite derrière tu places v à la place. Qu'essaies-tu de montrer?

                                                              -
                                                              Edité par Dan737 26 mai 2015 à 23:09:54

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Fonction qui retourne un résultat sans s'arrêter?

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown