Python: fonctions et compréhensions

Cette feuille donne quelques rappels de syntaxe Python et introduit un nouvel élément: les compréhensions.

De C++ à Python

Vous trouverez ci-dessous quelques rappels à propos du langage de programmation Python en comparaison avec C++:

  • les instructions sont séparées par des sauts de ligne (pas de ;)

  • les blocs sont déterminés par l’indentation (et non les accolades {})

  • le type est attaché aux valeurs et non aux variables

  • déclaration optionnelle des variables

  • déclaration optionnelle du type des entrées et sorties des fonctions
    mais c’est possible et recommandé par annotations de types

Constantes et affectations:

x = 42
message = "Bonjour!"
pi = 3.14159

Dans une cellule Jupyter: la valeur de la dernière expression est affichée:

message
x + pi

Avec un ; la dernière expression est vide; il n’y a donc rien d’affiché:

message
x + pi;

Les chaînes de format f"..." permettre de construire aisément des chaînes de caractères avec des paramètres:

f"La somme de x et pi vaut: {x+pi}; cela vaut bien un message: {message}"

Un if en C++:

if ( x < 10 ) {
    cout << "x est strictement plus petit que 10" << endl;
} else {
    cout << "x est plus grand que 10" << endl;
}

Le même if en Python:

if x < 10:
    print("x est strictement plus petit que 10")
else:
    print("x est plus grand que 10")

Une boucle for en C++:

for (int i = 0; i < 10 ; i++) {
    cout << i << endl;
}

La même boucle for en Python:

for i in range(0, 10):
    print(i)

range permet de construire des séquences d’entiers:

list(range(5, 10))
list(range(5, 95, 10))
list(range(10, 5, -1))

Fonctions mathématiques usuelles

from math import sin, cos, tan
sin(3.14)

Définir une fonction

En C++:

int f(int x, int y, int r) {
    return x + y - r
}

En Python:

def f(x, y, r):
    return x + y - r

Exercice: Écrire une fonction aire_rectangle(l,h) qui renvoie l’aire d’un rectangle de longueur l et de hauteur h.

### BEGIN SOLUTION
def aire_rectangle(l, h):
    return l * h
### END SOLUTION
assert aire_rectangle(3, 7) == 21

Il est possible – et même recommandé – de rajouter de la documentation, ainsi que des annotations de type. Ici nous précisons que les entrées et les sorties sont des nombres à virgule:

def f(x: float, y: float, r: float) -> float:
    """
    Renvoie x plus y moins r
    
    Ici, des explications sur la fonction
    """
    return x + y - r

Vous pouvez ensuite accéder à la documentation de la fonction comme d’habitude avec:

f?

Rajoutez de la documentation et des annotations de types à votre fontion aire_rectangle pour indiquer que les entrées et les sorties sont des entiers.

### BEGIN SOLUTION
def aire_rectangle(l: int, h: int) ->int:
    """
    Renvoie l'aire d'un rectangle de longueur l et hauteur h
    """
    return l * h
### END SOLUTION

À noter que les annotations de type ne sont pas vérifiées à l’exécution. Votre fonction acceptera quand même des arguments non entiers:

aire_rectangle(1.2, 1.3)

Ces annotations servent d’une part de documentation et d’autre part peuvent servir pour de l’analyse et statique de code pour détecter automatiquement d’éventuelles incohérences.

Les compréhensions

Les compréhensions sont un moyen confortable de construire des listes (ou autre collections) en en décrivant tous les éléments, avec une syntaxe proche de la notation mathématiques pour l’ensemble des \(f(x)\) pour \(x\) dans \(X\) tels que \(c(x)\):

\[ \{ f(x) \mid x\in X, c(x) \}\]

En Python la syntaxe est:

      [ <expr> for <name> in <iterable> ]
      [ <expr> for <name> in <iterable> if <condition> ]

Voici par exemple la liste des \(i^2\)\(i\) est dans \(\{1, 3, 7\}\):

[ i**2 for i in [1, 3, 7] ]

La même où \(i\) parcoure l’intervale \([0, 10[\):

[ i**2 for i in range(0, 10) ]

La liste des \(i^2\) dans l’intervale \([0,10[\) tels que \(i\) n’est pas divisible par trois:

[ i**2 for i in range(0, 10) if i % 3 != 0]

Exercice: Écrire une fonction aire_rectangles(h) qui renvoie la liste des surfaces de tous les rectangles de hauteur h et de largeur entière dans l’intervale \([1, 5[\), en utilisant votre fonction aire_rectangle:

### BEGIN SOLUTION
def aire_rectangles(h):
    return [aire_rectangle(l, h) for l in range(1, 5)]
### END SOLUTION
assert aire_rectangles(3) == [3, 6, 9, 12]