3 votes

Python : Utilisation d'un générateur dans une boucle while

Voici mon code jusqu'à présent :

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v
    return False

def up_data(v):
    t = 0
    h = 0
    vel = v
    while h < 1:
        t += .0001
        h = -4.9*t**2 - v*t
        vel = -9.8*t - v
        yield h, vel, t

Ce que j'essaye de faire, c'est de faire en sorte que mon main() pour sortir les valeurs de down_data(1) tant que cette fonction reste valide. L'exécution de ce code incomplet ne fait que créer une boucle infinie et je ne sais pas pourquoi.

J'essaie de combiner ces deux fonctions pour simuler une balle rebondissante, mais les assembler s'est avéré difficile à cause de la fonction de rendement. J'ai essayé de créer un main() et en cours d'exécution while boucle sur l'une des fonctions, mais cela crée une boucle infinie. Voici la main() J'ai essayé :

def main():
    data = [] 
    while down_data(1):
        data.append(down_data(1))
    print(data)

Existe-t-il un moyen plus simple de procéder ? Le site main() La fonction que je recherche serait quelque chose comme ça :

Edit : J'ai aussi essayé ceci, mais le même problème se produit ; la boucle while ne se ferme pas pour passer à la suivante. i :

def main():
    data = []
    for i in down_data(1):
        while i[0] > 0:
            data.append(i[0])
            continue
    print(data)

3voto

Ray Toal Points 35382

Les fonctions de génération en Python fonctionnent un peu différemment de la façon dont vous essayez de les utiliser.

Vous devez appeler down_data(1) une seule fois.

Essayez ça :

g = 9.8

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v

for h, v in down_data(1):
    print h, v

Cette opération générera un certain nombre de lignes de sortie, mais elle s'arrêtera lorsque h atteint 0.

Explication : Une fonction Python avec un yield dans celui-ci, lorsqu'il est appelé, produit un générateur. Chaque fois que vous appelez next sur le générateur, le générateur fonctionne jusqu'à ce qu'il atteigne une yield et les valeurs obtenues sont retournées à l'appelant. Si le générateur arrive à la fin de son corps sans rien produire, un message d'erreur StopIteration est soulevée.

Quand vous itérez sur un générateur dans un fichier for la boucle for se termine proprement lorsque le générateur n'a plus de données à fournir.

1voto

f5r5e5d Points 2435

Ray a raison de dire que les générateurs peuvent être gênants à utiliser en dehors de for e in gen qui cache l'exception StopIteration

mais non SyntaxError: 'return' with argument inside generator au moins en Python 3.5, Spyder IDE

g = 1

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v
    return 'fred' # this will be returned on StopIteration Exception

def mainly():
   data_gen =  down_data(1)
   data = [next(data_gen)]
   while data_gen:
       data.append(next(data_gen))
   #print(data)
   return len(data)        

principalement() échoue à cause de l'exception StopIteration, mais le retour down_data(h) est bien exécuté après l'exception :

 mainly()
Traceback (most recent call last):

  File "<ipython-input-103-015c95441865>", line 1, in <module>
    mainly()

  File "C:/Users/john/mypy/mySE_answers/tagd.py", line 48, in mainly
    data.append(next(data_gen))

StopIteration: fred

Un try/except explicite est nécessaire si vous allez jusqu'au bout du générateur avec vos propres appels next().

def my_try():
   data_gen =  down_data(1)
   try:
       data = [next(data_gen)]
       while True:
           data.append(next(data_gen))
   except: StopIteration

   return len(data), data[-1]

my_try()
Out[104]: (4518, (-0.0002038759998519435, 0.45179999999996656))

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