Certains points abordés ici serviront très peu ou seront abordés pendant l’année. Il s’agit d’approfondissement pour ceux qui ont déjà bien compris les parties précédentes.

"""On importe les bibliothèques scientifiques car elles seront utilisées ensuite"""
import numpy as np
import matplotlib.pyplot as plt

11. La compréhension des listes#

11.1. Position du problème#

On a vu que les listes classiques ne permettaient pas d’appliquer une fonction f à chaque élément en écrivant f(L) (L étant une liste classique). Cela a motivé l’utilisation des listes numpy. Néanmoins :

  • On est quelques fois obligé d’utiliser les listes classiques

  • La syntaxe f(L) ne fonctionne que si f est vectorialisable, c’est-à-dire programmée pour pouvoir s’appliquer à chaque élément.

Fonctions et opérateurs vectorialisables

Non exhaustif :

  • Les opérateurs classiues +,-,/,* sont vectorialisables

  • Les fonctions de la bibliothèques numpy (sin, cos, exp…) sont vectorialisables.

Un exemple fréquent est quand la fonction f fait appelle à un structure conditionnelle qui n’est pas vectorialisable. On reprend la fonction définie par morceau :

def fonction_morceau(x):
  if x < 3:  # Si x < 3
    a = x - 4
  elif x < 5:  # Si 3 <= x < 5
    a = x ** 2
  else:  # Si x >=5
    b = x + 4
    a = b ** 3
  return a

Impossible de l’appliquer directement à un vecteur numpy (pour la tracer par exemple:

x = np.linspace(0, 15, 1000)  # Vecteur de 1000 valeurs entre 0 et 15
y = fonction_morceau(x)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [3], line 2
      1 x = np.linspace(0, 15, 1000)  # Vecteur de 1000 valeurs entre 0 et 15
----> 2 y = fonction_morceau(x)

Cell In [2], line 2, in fonction_morceau(x)
      1 def fonction_morceau(x):
----> 2   if x < 3:  # Si x < 3
      3     a = x - 4
      4   elif x < 5:  # Si 3 <= x < 5

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The truth value of an array with more than one element is ambiguous. : Le message est clair : il cherche à travailler sur le vecteur et non sur chaque élément.

11.2. Première solution#

On peut écrire une boucle classique qui parcout tous les éléments de x et leur applique fonction_morceau :

x = np.linspace(0, 15, 1000)
y = np.zeros(len(x))  # On crée un vecteur nul qu'on va remplir

for i in range(len(x)):  # i prendra les indices de 0 à len(x) - 1
  y[i] = fonction_morceau(x[i])  # On remplit l'élément d'indice i


"""On peut même le tracer"""
f, ax = plt.subplots()  # On ne va pas légender le graphique puisqu'il n'y a pas de contexte ici.
ax.plot(x, y)

plt.show()
../_images/plus_loin_comprehension_9_0.png

11.3. Utilisation de la compréhension des listes.#

Une liste en compréhension est une liste qui est obtenue par action (et/ou filtrage) de chaque élément d’une autre liste. La syntaxe est simple :

L1 = [fonction(x) for x in L]  # L est une liste et L1 la nouvelle liste en compréhension

La syntaxe est assez clair : “Applique la fonction à x pour x qui parcourt chaque élément de L

Attention

Cette méthode renvoie une liste classique, pas un vecteur numpy. Si vous voulez obtenir un vecteur numpy, il faudra utiliser la fonction array :

L1 = np.array([fonction(x) for x in L])

A titre d’exemple :

x = np.linspace(0, 15, 1000)
y = np.array([fonction_morceau(i) for i in x])


"""On peut même le tracer"""
f, ax = plt.subplots()  # On ne va pas légender le graphique puisqu'il n'y a pas de contexte ici.
ax.plot(x, y)

plt.show()
../_images/plus_loin_comprehension_11_0.png