Devoir (deuxième partie)

Inversion House, photo Amber Case cc-by-nc
, par
Générateur
Le code suivant est valable en Python 2.7, mais pas en Python 3.5. Le traduire en Python 3.5. Comment peut-on faire pour transmettre une valeur au générateur ?
- def copain(nom, n):
- for i in range(n):
- yield ('%s : %d' %(nom, i))
- yield ('Bob : bye')
- def main():
- generateur = copain('Bob', 5)
- print generateur.next()
- generateur.send('salut bob') # cette valeur sera donnée au yield
- for i in generateur:
- print i
- main()
Inverser l’inversion du contrôle
Nous avons vu comment utiliser les coroutines pour (re)inverser le
contrôle. Typiquement si nous prenons un programme dans lequel tout le
traitement est effectué par une fonction (typiquement un main
) qui a
le contrôle de l’exécution du début à la fin et peut faire des appels
à l’environnement pour récupérer des données et que nous voulons
transformer ce programme en un programme dans lequel il y a une boucle
événementielle principale qui passe les données de l’environnement une
par une à une fonction (une callback
), nous pouvons utiliser une
transformation en générateur, ou plus précisément une transformation
en coroutine (apte à recevoir des données envoyées par send()
).
Soit le programme :
- def avancer():
- print "avancer d'une case"
- def tg():
- print "tourner à gauche de 90°"
- def obstacle():
- """
- retourne True s'il y a un obstacle devant le robot
- """
- return False
- def main():
- for i in range(10):
- while not obstacle():
- avancer()
- tg()
- main()
Compléter le programme suivant pour achever la reécriture en programme
avec boucle événementielle.
- import time
- def avancer():
- return "avancer"
- def tg():
- return "tg"
- def robot_obstacle():
- return False
- def robot_execute(s):
- print "execution de l'ordre : ", s
- # /!\ variable globale
- env = {'obstacle': False}
- def main():
- yield "debut de main"
- for i in range(10):
- while not env["obstacle"]:
- yield avancer()
- yield tg()
- env["callback"] = TODO_COMPLETER
- def main_loop(callback):
- print callback.next()
- for i in range(1000):
- env['obstacle'] = robot_obstacle()
- time.sleep(1)
- ordre_robot = TODO_COMPLETER
- robot_execute(ordre_robot) # execture un ordre
- print 'fin de la boucle evt'
- main_loop(env["callback"])
Version Python 3.5.
Donner une version Python 3.5 de ce programme avec boucle
événementielle.
Délégation à un sous-générateur.
Supposons que dans le code non événementiel, dans le main, on ait
délégué une partie du traitement à une fonction qui passe plusieurs
ordres au robot. Comment aurait-on pu réécrire le programme de façon événementielle ? Répondre en Python 2.7 et en Python 3.5.
- ...
- def avancer_obstacle():
- while not obstacle():
- avancer()
- def main():
- for i in range(10):
- avancer_obstacle()
- tg()
- ...
Vous rendrez cette seconde partie du devoir avant mardi 8 décembre 8h30, en utilisant un format ouvert. Un format texte (avec éventuellement une syntaxe markdown) incluant les programmes serait parfait. Sinon (pdf etc.) assurez-vous qu’il soit facile de copier/coller le code de vos programmes dans un fichier texte.