yield
Énoncé
Écrire un générateur permettant d'afficher les maxi premiers nombres premiers, où maxi est un nombre donné en paramètre.
Par exemple, ./premiers.py 6 affichera :
Pour ce faire, vous compléterez le fichier premiers.py disponible ici et affiché ci-dessous.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 | #!/usr/bin/env python3
"""Générateur des premiers nombres premiers"""
import sys
import math
def est_premier(number):
"""La complexité n'est pas le sujet ici, donc on a fait ça
naïvement."""
for diviseur in range(2, int(math.sqrt(number)) + 1):
if (number % diviseur) == 0:
return False
return True
def genere_premiers():
"""Générateur infini de nombres premiers.
La complexité n'est pas le sujet ici, donc on a fait ça
naïvement. Et donc, attention à ne pas tester avec un maxi trop
grand pour ne pas attendre trop longtemps, et surtout user la
planète avec des calculs inutiles.
"""
# 2 est premier,on le sait, alors on le renvoie directement
# pour le plaisir, et voir que yield peut s'utiliser en dehors
# d'une boucle
yield 2
# Ensuite on itère à l'infini, Python est génial !
# TODO
...
def test():
"""Teste le générateur des premiers nombres premiers"""
# L'utilisateur donne maxi
if len(sys.argv) == 1:
print("Usage :", sys.argv[0], "maxi")
return
maxi = int(sys.argv[1])
# On affiche
gen_premiers = genere_premiers()
nb_affiche = 0
while nb_affiche < maxi:
print(next(gen_premiers))
nb_affiche += 1
if __name__ == "__main__":
test()
|
Correction
Cliquez ici pour révéler la correction.
Grâce au transfert du flot de contrôle effectué par le yield, on peut en Python écrire des boucles infinies qui n'en sont pas vraiment.
Voici donc le code de correction :
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 | #!/usr/bin/env python3
"""Générateur des premiers nombres premiers"""
import sys
import math
def est_premier(number):
"""La complexité n'est pas le sujet ici, donc on a fait ça
naïvement."""
for diviseur in range(2, int(math.sqrt(number)) + 1):
if (number % diviseur) == 0:
return False
return True
def genere_premiers():
"""Générateur infini de nombres premiers.
La complexité n'est pas le sujet ici, donc on a fait ça
naïvement. Et donc, attention à ne pas tester avec un maxi trop
grand pour ne pas attendre trop longtemps, et surtout user la
planète avec des calculs inutiles.
"""
# 2 est premier,on le sait, alors on le renvoie directement
# pour le plaisir, et voir que yield peut s'utiliser en dehors
# d'une boucle
yield 2
# Ensuite on itère à l'infini, Python est génial !
number = 3
while True:
if est_premier(number):
# Plutôt que de construire une list (== un vecteur) avec
# tous les nombres premiers, on rend la main dès qu'on
# en trouve un
yield number
number += 1
def test():
"""Teste le générateur des premiers nombres premiers"""
# L'utilisateur donne maxi
if len(sys.argv) == 1:
print("Usage :", sys.argv[0], "maxi")
return
maxi = int(sys.argv[1])
# On affiche
gen_premiers = genere_premiers()
nb_affiche = 0
while nb_affiche < maxi:
print(next(gen_premiers))
nb_affiche += 1
if __name__ == "__main__":
test()
|