Skip to content

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 :

1
2
3
4
5
6
2
3
5
7
11
13

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()