Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercice : mise en cache des fonctions

    22 juin 2011 à 16:59:00

    Ben fred1599, c'est tout simple : une fois que tu as défini ton décorateur, les deux codes suivants sont équivalents :
    @deco
    def f(x):
        blabla
    

    def f(x):
        blabla
    f = deco(f)
    


    Candide, tu pensais vraiment que le boarf de xarch voulait avoir une valeur pédagogique ? À mon avis il est surtout là pour relativiser ce que dit fred1599 et dire que, finalement, les décorateurs, c'est conceptuellement très simple (ah, c'est sûr, il faut connaître les fonctions d'ordre supérieur. Mais encore une fois, avec un minimum de pratique en python ou - mieux - dans un langage fonctionnel, ça ne devrait poser aucun problème).
    • Partager sur Facebook
    • Partager sur Twitter
      22 juin 2011 à 17:02:50

      Ce que je disais était sur un scope plus large que Python en lui-même.

      Si on se met à la place d'un débutant en programmation qui aurait commencé son apprentissage avec "un langage fonctionnel" (et ça existe… mes premiers cours d'info étaient en CamL), je ne serais pas étonné qu'il saisisse relativement facilement l'usage de features comme les map/reduce/closures/décorateurs, et se retrouve comme un con devant une boucle while, ou la gestion des exceptions.

      Edit : grilled by Orrita
      • Partager sur Facebook
      • Partager sur Twitter
      Zeste de Savoir, le site qui en a dans le citron !
        22 juin 2011 à 17:06:05

        J'en profite pour faire remarquer à candide que je ne saisis pas bien la valeur pédagogique de ses propres interventions.
        • Partager sur Facebook
        • Partager sur Twitter
          22 juin 2011 à 17:06:23

          Mauvais exemple, on a des exceptions en caml, et, même si ce style de code est laid, des boucles.

          Silemce, Maxibolt.
          • Partager sur Facebook
          • Partager sur Twitter
            22 juin 2011 à 17:06:50

            Exemple, c'est masculin, c'est pas comme chipolata.
            • Partager sur Facebook
            • Partager sur Twitter
              22 juin 2011 à 17:14:25

              Citation : Orrita

              une fois que tu as défini ton décorateur, les deux codes suivants sont équivalents :

              @deco
              def f(x):
                  blabla
              


              def f(x):
                  blabla
              f = deco(f)
              


              gné ?
              décidement je pigerai jamais ... o_O
              • Partager sur Facebook
              • Partager sur Twitter

              Python c'est bon, mangez-en. 

              Anonyme
                22 juin 2011 à 17:24:05

                Citation

                gné ?
                décidement je pigerai jamais ...



                Et pourtant Josmiley est expérimenté en python :)

                Tu vois la pédagogie ne doit pas couvrir que 50 % des utilisateurs, mais 90 à 95 % si on considère que les 5 à 10 autres pourcents, se sont plutôt des gens qui y mettent de la mauvaise volonté.

                On peut donc dire ( ton code ne me permettra pas de m'améliorer, ce n'est pas une base sur laquelle je peux m'appuyer ) que pédagogiquement parlant ce n'est pas un code suffisant.

                D'ailleurs je ne suis pas sûr qu'un seul code permet d'avoir une base sur les décorateurs.

                Le problème c'est que même dans les docs officielles c'est très mal expliqué concrètement, et je dirais que c'est un peu normal car c'est plus considéré comme du sucre syntaxique.

                Mais comme tout sucre, c'est pratiquement toujours inutile ou non optimisé.
                • Partager sur Facebook
                • Partager sur Twitter
                  22 juin 2011 à 17:26:34

                  Citation : candide


                  le Boarf en guise de pédagogie ...



                  Tu veux bien arrêter de toujours parler de « pédagogie » ? On dirait Shivaan qui parle de « respect ». À force, ça perd son sens et son intérêt comme mot.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    22 juin 2011 à 17:28:55

                    @josmiley : tout ce que montre le second code, c'est qu'une fonction n'est qu'un objet comme un autre.

                    Quand tu appelles une fonction en python, c'est, pour résumer grossièrement comme quand tu appelles la méthode __call__ d'un objet quelconque. Au final, le décorateur va remplacer "l'instance" de la fonction par une version améliorée d'elle-même, un peu comme quand tu fais maliste = sorted(maliste) sur un objet quelconque.

                    Je pense qu'il est difficile de fournir des explications plus simples comme ça sans schéma.
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Zeste de Savoir, le site qui en a dans le citron !
                      22 juin 2011 à 17:29:47

                      Comme tout sucre, parler d'optimisation n'a pas de sens... Une façon plus agréable d'écrire exactement la même chose n'a rien à voir avec une optimisation.

                      Je ne vois vraiment pas ce qui n'est pas clair dans ce que j'ai expliqué. Le deuxième code est tout ce qu'il y a de plus banal en Python, et le premier lui est exactement équivalent.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        22 juin 2011 à 17:42:30

                        Citation

                        Je ne vois vraiment pas ce qui n'est pas clair dans ce que j'ai expliqué. Le deuxième code est tout ce qu'il y a de plus banal en Python, et le premier lui est exactement équivalent.



                        Euh... Oui je l'ai compris ton code, ce que je veux dire c'est que ton code est clair pour toi, moi mais pas pour josmiley qui pourtant est un utilisateur expérimenté.

                        les décorateurs c'est du sucre syntaxique, mais c'est aussi une fonction, pourquoi ne pourrait-elle pas être optimisée ou optimiser?

                        Ce que je veux dire, c'est surtout que le sucre syntaxique (même si des fois je le fais aussi) est pratiquement toujours inutile et au dépend d'une difficulté dans la lisibilité du code en plus.

                        Enfin bref, le 2ème code est beaucoup plus lisible que le 1er, en ce qui me concerne en tout cas.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          22 juin 2011 à 17:53:12

                          Citation : Orrita

                          Ben fred1599, c'est tout simple : une fois que tu as défini ton décorateur, les deux codes suivants sont équivalents



                          Je suis sûr que fred le sait. Ce n'est pas parce qu'on comprend tous les mots d'une histoire drôle qu'on va forcément rire. C'est pas parce qu'on connait la lettre E, le lettre m, la lettre c et qu'on sait ce qu'est un carré qu'on a compris la relativité.


                          Citation : Orrita


                          Candide, tu pensais vraiment que le boarf de xarch voulait avoir une valeur pédagogique ?



                          Une valeur condescendante :lol:


                          Citation : Orrita


                          À mon avis il est surtout là pour relativiser ce que dit fred1599 et dire que, finalement, les décorateurs, c'est conceptuellement très simple




                          Sauf que si tu réduis les décorateurs à leur pure définition, comme le dit Kent's Korner
                          , tu t'en passes. Bien évidemment, ce qui fait que la notion de décorateur est complexe est la richesse de ses situations d'utilisation. Rien que le décorateur du toy-example résolu par Nohar contient la définition d'une fonction elle-même décorée. Tout ça à travers un exemple qui n'est pas vraiment convaincant comme tu le reconnais toi-même.




                          Citation : Orrita


                          Mais encore une fois, avec un minimum de pratique en python ou - mieux - dans un langage fonctionnel, ça ne devrait poser aucun problème).



                          OK et si ça en pose, tu proposes quoi ? le gaz ou la corde ?
                          • Partager sur Facebook
                          • Partager sur Twitter
                            22 juin 2011 à 17:53:56

                            je ne comprends pas parce que je ne vois pas à quoi ça peut servir ...
                            exemple: j'ai rien pigé à property() jusqu'au jour où j'ai eu besoin d'un système qui modifie dynamiquement des attributs; et là qq1 m'a dit: "regardes property()..." et c'est devenu clair.

                            donc, sans comprendre l'utilité des décorateurs, je ne risque pas d'en comprendre le fonctionnement.
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Python c'est bon, mangez-en. 

                              22 juin 2011 à 17:54:04

                              Le sucre syntaxique n'a pas pour but d'être utile, mais de rendre la lecture plus agréable... Et avec un peu d'habitude, le premier code est effectivement plus agréable à lire.

                              josmiley, en soi les décorateurs n'apportent rien (tout comme property : on pourrait avoir le même résultat autrement). Mais c'est comme dire qu'une fonction n'apporte rien parce qu'on pourrait réécrire le code à chaque appel.

                              candide, je reconnais surtout que critiquer les décorateurs en se basant sur l'exemple choisi est débile. Personne de censé n'utiliserait cet exemple dans le cas réel, c'est évident. Il reste quand l'utilisation que j'en fais, à savoir s'en servir pour tester la validité de son code, est entièrement justifiée.

                              Si ça pose des problèmes, je recommande de se mettre un peu plus sérieusement à python.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                22 juin 2011 à 17:56:35

                                Arrête d'insister, Orrita, candide est prof de fac. Des vrais cons, il en croise tous les jours beaucoup plus que toi, donc il a raison.

                                josmiley> Je croyais que tu utilisais @property ? Tu utilises un truc utile qui utilise les décorateurs. Techniquement, tu devrais en déduire que les décorateurs sont utiles eux aussi.

                                L'idée des décorateurs est de te permettre de rajouter un comportement à une fonction sans modifier ton code, en la "décorant". Tu peux t'en servir pour ajouter un système de cache comme ici, pour l'ajouter à un callback, pour automatiquement loguer ses entrées et ses sorties (voir l'exercice de NoHaR euh, ailleurs)… Tu sépares le code de cette fonction (qui est pur) avec l'effet rajouté (une décoration).

                                Mais il n'y a pas de secret, c'est en pratiquant que tu arriveras à sentir le truc ou pas. Par contre ça sert à rien de répéter 4 fois que tu vois pas à quoi ça sert.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  22 juin 2011 à 18:00:20

                                  Citation : josmiley


                                  donc, sans comprendre l'utilité des décorateurs, je ne risque pas d'en comprendre le fonctionnement.




                                  Absolument.

                                  Citation : Orrita

                                  Le sucre syntaxique n'a pas pour but d'être utile, mais de rendre la lecture plus agréable... Et avec un peu d'habitude, le premier code est effectivement plus agréable à lire.



                                  Donc, pour comprendre les décorateurs, il faut aller derrière le sucre syntaxique et comprendre certains contextes et un contexte, c'est du temps, de l'expérience, du questionnement, tout sauf le simplisme dont tu n'arrives pas à sortir, et dire qu'on est sur le siteduZÉRO, là pour le coup, coefficient empathique = ZÉRO.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    22 juin 2011 à 18:03:04

                                    Citation : candide

                                    Citation : josmiley


                                    donc, sans comprendre l'utilité des décorateurs, je ne risque pas d'en comprendre le fonctionnement.



                                    Absolument.



                                    Bullshit. On peut comprendre le principe (et, avec un peu plus d'effort, le fonctionnement) des décorateurs sans arriver à les appliquer. C'est pas difficile : un décorateur est une fonction qui prend une fonction en argument, et renvoie une autre fonction. C'est peut-être peu naturel pour des gens qui ont décidé de ne pas chercher à faire d'effort, mais ça n'est pas difficile pour autant.

                                    DE PLUS : de manière évidente, josmiley code en Python comme on coderait en Java, il n'a aucune expérience avec ce langage, et il a certainement été (mal) influencé par une trop grande pratique d'autres langages plus idiots que Python.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      22 juin 2011 à 18:04:19

                                      Bon, alors je dois être un génie pour avoir compris que les décorateurs étaient simples. Désolé de vous ennuyer avec mon niveau hors de portée de débutants comme vous.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Anonyme
                                        22 juin 2011 à 18:15:21

                                        Savoir des choses inutiles ne démontrent pas un savoir faire ;)

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          22 juin 2011 à 18:18:01

                                          Je ne vois pas le rapport.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            22 juin 2011 à 18:21:15

                                            je crois que je viens de piger un truc en comparent aux class ...
                                            pour un décorateur donné; les fonctions décorées doivent avoir un fonctionnement commun.
                                            est-ce que je peux comparer un décorateur à une méthode commune à des class différentes ?
                                            par exemple str.count() et list.count() ...
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Python c'est bon, mangez-en. 

                                              22 juin 2011 à 18:24:48

                                              josmiley> Qu'est-ce que tu ne comprends pas dans "un décorateur est une fonction qui accepte une fonction en argument, et renvoie une autre fonction" ?
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                22 juin 2011 à 18:40:28

                                                Citation : ChipolataGratiné

                                                josmiley> Qu'est-ce que tu ne comprends pas dans "un décorateur est une fonction qui accepte une fonction en argument, et renvoie une autre fonction" ?



                                                non mais je crois que j'ai compris; en prenant du recul ... pas tout mais au moins le principe.
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Python c'est bon, mangez-en. 

                                                  22 juin 2011 à 18:45:54

                                                  Je tenais à faire remarquer que l'utilisation d'un try/except en lieu et place du test de présence (in) améliore un peu les performances :
                                                  $ python becnh.py
                                                  Fibo avec `in` :  3.22333653768
                                                  Fibo avec `try` :  2.57666349411


                                                  from functools import wraps
                                                  from time import time
                                                  
                                                  def cached_in(fn):
                                                      fn.cachedict = {}
                                                      @wraps(fn)
                                                      def wrapper(*args):
                                                          argskey = tuple(args)
                                                          if argskey in fn.cachedict:
                                                              ret = fn.cachedict[argskey]
                                                          else:
                                                              ret = fn.cachedict[argskey] = fn(*args)
                                                          return ret
                                                      return wrapper
                                                  
                                                  def cached_try(fn):
                                                      fn.cachedict = {}
                                                      @wraps(fn)
                                                      def wrapper(*args):
                                                          argskey = tuple(args)
                                                          try:
                                                              ret = fn.cachedict[argskey]
                                                          except KeyError:
                                                              ret = fn.cachedict[argskey] = fn(*args)
                                                          return ret
                                                      return wrapper
                                                  
                                                  @cached_in
                                                  def fibo_in(n):
                                                      if n <= 1:
                                                          return 1
                                                      else:
                                                          return fibo_in(n-1) + fibo_in(n-2)
                                                  
                                                  @cached_try
                                                  def fibo_try(n):
                                                      if n <= 1:
                                                          return 1
                                                      else:
                                                          return fibo_in(n-1) + fibo_in(n-2)
                                                  
                                                  def bench(n, l):
                                                      t = time()
                                                      for i in xrange(n):
                                                          fibo_in(l)
                                                      t_in = time() - t
                                                  
                                                      t = time()
                                                      for i in xrange(n):
                                                          fibo_try(l)
                                                      t_try = time() - t
                                                  
                                                      return t_in, t_try
                                                  
                                                  if __name__ == '__main__':
                                                      iter, n, l = 30, 30000, 50
                                                      res = [bench(n, l) for i in xrange(iter)]
                                                      print('Fibo avec `in` : ', sum(_[0] for _ in res)/float(iter)*100)
                                                      print('Fibo avec `try` : ', sum(_[1] for _ in res)/float(iter)*100)
                                                  
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    22 juin 2011 à 18:47:35

                                                    Citation : Zopieux

                                                    Je tenais à faire remarquer que l'utilisation d'un try/except en lieu et place du test de présence (in) améliore un peu les performances :

                                                    $ python becnh.py
                                                    Fibo avec `in` :  3.22333653768
                                                    Fibo avec `try` :  2.57666349411


                                                    http://docs.python.org/glossary.html#term-eafp ;)
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      22 juin 2011 à 18:50:12

                                                      Je pense que le plus difficile n'est pas de comprendre comment fonctionne un décorateur et à quoi ça sert, mais de savoir à quel moment et dans quelle situation on devrait les utiliser (en tout cas me concernant).

                                                      Pour suivre.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                      Anonyme
                                                        22 juin 2011 à 18:59:42

                                                        Citation

                                                        Je pense que le plus difficile n'est pas de comprendre comment fonctionne un décorateur et à quoi ça sert, mais de savoir à quel moment et dans quelle situation on devrait les utiliser (en tout cas me concernant).



                                                        ça te permet d'éviter des contrôles identiques dans toutes les fonctions de ton code.

                                                        Imaginons que tu es à tester le type d'un argument et que tu dois le faire dans 40 fonctions, tu ne vas pas taper ce code dans chaque fonction

                                                        if isinstance(arg, int):
                                                            #suite de ma fonction
                                                        


                                                        à l'aide des décorateurs tu peux éviter de te retaper ces 2 lignes sur tes 40 fonctions, en ajoutant au-dessus de la fonction concernée le décorateur @testing_arg par exemple.

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          22 juin 2011 à 19:18:49

                                                          L'exemple de NoHaR (sur un autre sujet) était bien aussi : pour tracer les appels de fonctions, il est plus propre de mettre @trace devant plutôt que de rajouter au début et à la fin de chaque fonction le code en question...
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            22 juin 2011 à 19:29:53

                                                            Citation : ChipolataGratiné

                                                            http://docs.python.org/glossary.html#term-eafp ;)


                                                            Voilà, c'est justement ce que je ne trouvais plus.
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Exercice : mise en cache des fonctions

                                                            × 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