Skip to article frontmatterSkip to article content

principalement les structures de contrôle, et quelques-unes plus anecdotiques
nous laissons intentionnellement de coté le for pour le moment, ainsi que le try..except

l’instruction if

L’instruction conditionnelle en Python:

if <test1>:
    <statement1>
elif <test2>:
    <statement2>
...
else:
    <statement4>

repose sur une évaluation dite paresseuse, c’est-à-dire que l’instruction s’arrête au premier test qui est vrai (on n’évalue pas les tests suivants)

# par exemple

def appreciation(note):
    if note >= 16:
        return "félicitations"
    elif note >= 14:
        return "compliments"
    elif note >= 12:
        return "encouragements"
    elif note >= 10:
        return "passable"
    else:
        return "insuffisant"
print(appreciation(15.5))
compliments
print(appreciation(11.5))
passable

if (l’expression)

il existe aussi une expression permettant de faire quelque chose comme if .. then .. else ..
la syntaxe générale est

<exp_1> if <test> else <exp_2>
note = 8

# et comme c'est une expression, je peux par exemple
# la passer à une fonction

print("insuffisant" if note < 10 else "ouf !")
insuffisant

boucle while

while <test>:
    bloc d_instructions
    alignés comme on l_a vu
else:
    bloc     # exécuté à la sortie de la boucle 
    aligné   # seulement s’il n’y a pas de break

break, continue

deux instructions particulières:

on parle toujours de la boucle la plus imbriquée

# exemple avec continue
# on veut zapper les nombres pairs

L = [1, 5, 2, 7, 9]

while L:
    n = L.pop()
    if n % 2 == 0:
        continue
    # ... faire des trucs compliqués avec n
    print(f"{n=}", end=" ")
n=9 n=7 n=5 n=1 
# exemple avec break
# dès qu'on trouve un nombre pair on s'arrête

L = [1, 5, 2, 7, 9]

while L:
    n = L.pop()
    if n % 2 == 0:
        break
    # ... faire des trucs compliqués avec n
    print(f"{n=}", end=" ")
n=9 n=7 

match .. case

une toute nouvelle instruction match permet de définir des alternatives selon:

# dans une version à-la switch

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case 401 | 403 :
            return "Not allowed"
        case _:
            return "Something's wrong with the internet"

print(http_error(404))
Not found
# mais on peut faire aussi plus complexe
# avec du pattern-matching, ici sur la valeur
# dans un tuple

def on_values(point: tuple[float, float]):
    match point:
        case (0, 0):
            return "Origin"
        case (0, y):
            return f"null-x Y={y}"
        case (x, 0):
            return f"null-y X={x}"
        case (x, y):
            return f"regular X={x}, Y={y}"
        case _:
            raise ValueError("Not a point")

P = (0, 20)
print(on_values(P))
null-x Y=20
# ou encore ici sur la taille d'un objet

def on_size(string):
    match string.split():
        case []:
            return "no word"
        case [w]:
            return f"one word {w}"
        case first, *rest:
            return f"multi words starting with `{first}`"

print(on_size(""))
print(on_size("a b c"))
no word
multi words starting with `a`

pour une introduction plus complète, voyez ceci https://peps.python.org/pep-0636/

return

return sert tout simplement à indiquer la fin d’une fonction, et ce qu’elle doit renvoyer
lorsque le programme atteint cette instruction, la fonction courante s’arrête immédiatement

pass

l’instruction pass ne fait rien; elle est en général utilisée lorsque la syntaxe demande une instruction, mais qu’on ne l’a pas encore implémentée

def ma_fonction():
    pass

class Foo:
    pass

libération de variables: del

exécuter du code

(avancé)

nous allons voir à présent deux fonctions, donc tehcniquement ce ne sont pas des instructions, mais bon ce n’est pas important

exec() et eval()

exec() pour une instruction

# instructions
i1 = """def fact(n):
    return 1 if n <= 1 else n * fact(n-1)"""
i2 = """if fact(2) > 1:
    print('OUI')"""
# on peut les exécuter
# ceci ne fait rien que de définir une fonction
print(exec(i1))
None
fact
<function __main__.fact(n)>
# qu'on peut maintenant utiliser au travers de i2
# l'impression ici est faire dans le code de i2
# et puis None est le retour de exec
print(exec(i2))
OUI
None
# par contre exec() ne renvoie rien d'utile
print(exec("fact(3)"))
None

exec() vs eval()

# expressions
e1 = '(2+3)/2.0'
e2 = "{'alice' : 35, 'bob' : 8}"
# on peut aussi les exécuter (une expression est une instruction)
# mais le retour est None ce qui perd de son intérêt
print(exec(e1))
None
# c'est mieux de les évaluer
print(eval(e1))
2.5
print(eval(e2)['alice'])
35

eval() pour une expression

# par contre on ne peut pas évaluer une instruction
try:
    res = eval(i1)      # i1 est une instruction
except Exception as e:
    print("Exception {} - {}".format(type(e), e))
    import traceback
    traceback.print_exc()
Exception <class 'SyntaxError'> - invalid syntax (<string>, line 1)

Traceback (most recent call last):
  File "/tmp/ipykernel_2561/1447414021.py", line 3, in <module>
    res = eval(i1)      # i1 est une instruction
          ^^^^^^^^
  File "<string>", line 1
    def fact(n):
    ^^^
SyntaxError: invalid syntax

use with care