IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Générateurs en folie !


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut Générateurs en folie !
    Bonjour,

    en voulant coder un petit truc de math sur les suites, je suis tombé sur un comportement que je ne m'explique pas :

    J'ai un générateur A d'int (ie un fonction qui fait des yield et avec laquelle on peut faire for i in A(): ).

    J'ai un autre générateur d'int D qui prend en paramètre un générateur d'int et qui renvoie la différence entre 2 éléments consécutifs de ce dernier.

    J'aimerais fabriquer un troisième générateur qui ferait des appels récursifs des 2 précédents...

    Bon, si ce n'est pas super clair, voici un exemple simplifié qui synthétise mon problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    def A ( nb ):  # générateur d'int tout simple
        for i in xrange( nb ):
            yield i*i*i
     
    def D ( suite ):  # générateur qui calcule la "dérivée" d'un autre générateur
        p = None
        for i in suite :
            if p is not None :
                yield i-p
            p = i
     
    def print_suite ( suite ): # outil d'affichage
        print suite,'--->',
        for n in suite :
            print n,
        print             
     
    def test1 ( nb ):  # fonction qui fait ce que je veux mais avec une profondeur de récursion codée "en dur"
        print_suite( A( nb ))
        print_suite( D( A( nb )))
        print_suite( D( D( A( nb ))))
        print_suite( D( D( D( A( nb )))))
     
    def test2 ( nb,prof ):  # fonction qui devrait faire ce que je veux, mais en fait non...
        suite = A( nb )
        for i in xrange( prof ):
            print_suite( suite )
            suite = D( suite )
     
    def test3 ( nb,prof ):  # autre tentative qui ne fonctionne pas non plus...
        suites = [A( nb )]
        for i in xrange( prof ):
            suites += [D( suites[-1] )]
        for s in suites :
            print_suite( s )
     
    test1( 20 )    
    test2( 20,4 )    
    test3( 20,4 )
    ce qui me donne l'affichage suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <generator object A at 0x025D7F30> ---> 0 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375 4096 4913 5832 6859
    <generator object D at 0x025D7F58> ---> 1 7 19 37 61 91 127 169 217 271 331 397 469 547 631 721 817 919 1027
    <generator object D at 0x025D7E90> ---> 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108
    <generator object D at 0x025D7F80> ---> 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
    <generator object A at 0x025D7F80> ---> 0 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375 4096 4913 5832 6859
    <generator object D at 0x025D7F58> --->
    <generator object D at 0x025D7F80> --->
    <generator object D at 0x025D7F58> --->
    <generator object A at 0x025D7F80> ---> 0 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375 4096 4913 5832 6859
    <generator object D at 0x025D7F30> --->
    <generator object D at 0x025D7F58> --->
    <generator object D at 0x025D7E90> --->
    <generator object D at 0x025D7FA8> --->
    test1 fait bien ce que j'attends, mais il ne me permet pas de passer la profondeur de la récursion en paramètre. test2 et test3 le permettent mais ne fonctionnent pas : comme on voit, à part la première suite, ils n'affichent rien.

    Je pense que je n'ai pas tout compris à propos des générateurs...

    Si quelqu'un comprend pourquoi test2 et test3 ne font pas comme test1, ou comment coder une fonction qui fait comme test1 mais permet de choisir la profondeur de la récursion...

    Merci d'avance

  2. #2
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Dans tes fonctions 2 et 3, tu consommes à chaque fois le premier générateur (A()), avant de consommer les suivants, qui travaillent donc sur rien.

    C’est une limitation connue des générateurs, il n’y a pas de moyen satisfaisant de les copier (cf. aussi http://bugs.python.org/issue11299).

    La solution la plus simple dans ton cas est de n’afficher que le dernier itérateur*!

    On peut utiliser itertools.tee(), mais celui-ci se contente de copier dans un cache interne les éléments générés par la copie la plus “en avance”, tant qu’ils n’ont pas été consommés par la copie la plus “en retard”, ce qui enlève l’un des principaux intérêts des générateurs (ne pas encombrer la mémoire).

    Une autre solution (probablement adaptée à ton cas) consiste à utiliser des fonctions génératrices de générateurs (), ce qui pourrait donner ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    def A ( nb ):  # générateur d'int tout simple
        for i in xrange( nb ):
            yield i*i*i
     
    def D ( suite ):  # générateur qui calcule la "dérivée" d'un autre générateur
        p = None
        for i in suite :
            if p is not None :
                yield i-p
            p = i
     
    def print_suite ( suite ): # outil d'affichage
        print suite,'--->',
        for n in suite :
            print n,
        print
     
    def _gen_n(nb, prof):
        gen = A(nb)
        for i in xrange(prof):
            gen = D(gen)
        return gen
     
    def test4(nb, prof):
        for i in xrange(prof):
            print_suite(_gen_n(nb, i))
     
    test1( 20 )    
    test2( 20,4 )    
    test3( 20,4 )
    test4( 20,4 )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <generator object A at 0x2710dc0> ---> 0 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375 4096 4913 5832 6859
    <generator object D at 0x2710d70> ---> 1 7 19 37 61 91 127 169 217 271 331 397 469 547 631 721 817 919 1027
    <generator object D at 0x2710c80> ---> 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108
    <generator object D at 0x2710c30> ---> 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6

  3. #3
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    arf ! j'ai compris, j'ai corrigis et ça a marchi !

    En fait c'est mon print_suite que me "consomme" mes générateurs...

    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Quel est le meilleur générateur d'états selon vous ?
    Par Marc Lussac dans le forum Outils de restitution et d'analyse
    Réponses: 80
    Dernier message: 18/05/2010, 16h43
  2. Que pensez-vous des générateurs de doc PHP ?
    Par Nonothehobbit dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 64
    Dernier message: 10/07/2007, 10h17
  3. [C++ builder] Comment utiliser un générateur d'ID?
    Par Nicodemus dans le forum Débuter
    Réponses: 2
    Dernier message: 17/05/2004, 13h25
  4. Générateur de doc
    Par chman dans le forum Langages de programmation
    Réponses: 7
    Dernier message: 09/09/2003, 20h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo