Leçon 6

Les bases de Python

  • Aujourd'hui, nous allons apprendre un nouveau langage de programmation appelé Python. Gardez à l'esprit que l'un des objectifs généraux du cours n'est pas d'apprendre des langages particuliers, mais comment programmer en général.
  • Le code Python semble beaucoup plus simple que le C, mais il est capable de résoudre des problèmes dans des domaines comme la science des données. En fait, pour afficher "bonjour le monde", il suffit d'écrire :

      print("bonjour, le monde")
    
    • Notez que, contrairement au C, nous n'avons pas besoin d'importer une bibliothèque standard, de déclarer une fonction main, de spécifier un saut de ligne dans la fonction print ou d'utiliser des points-virgules.
  • Python est un langage interprété, ce qui signifie que nous exécutons en fait un autre programme (un interpréteur) qui lit notre code source et l'exécute de haut en bas. Par exemple, nous pouvons enregistrer le code ci-dessus sous la forme hello.py et exécuter la commande python hello.py pour exécuter notre code, sans avoir à le compiler.

  • Nous pouvons obtenir des chaînes d'un utilisateur :

      answer = get_string("Quel est votre nom ?\n")
      print("bonjour, " + answer)
    
    • Nous créons une variable appelée answer, sans spécifier le type (l'interpréteur le détermine à partir du contexte pour nous), et nous pouvons facilement combiner deux chaînes avec l'opérateur + avant de la passer à print.
    • Nous pouvons également transmettre plusieurs arguments à print, avec print("bonjour,", answer), et il les joindra automatiquement avec des espaces pour nous aussi.
    • print accepte également les chaînes de format telles que f"bonjour, {answer}", qui substituent les variables entre accolades dans une chaîne.
  • Nous pouvons créer des variables avec juste counter = 0. Pour incrémenter une variable, nous pouvons utiliser counter = counter + 1 ou counter += 1.

  • Les conditions ressemblent à :

      if x < y:
          print("x est inférieur à y")
      elif x > y:
          print("x est supérieur à y")
      else:
          print("x est égal à y")
    
    • Contrairement au C et au JavaScript (où les accolades {``} sont utilisées pour indiquer des blocs de code), l'indentation exacte de chaque ligne est ce qui détermine le niveau d'imbrication en Python.
    • Et au lieu de else if, nous disons simplement elif.
  • Les expressions booléennes sont également légèrement différentes :

      while True:
          print("bonjour, le monde")
    
  • Nous pouvons écrire une boucle avec une variable :

      i = 3
      while i > 0:
          print("tousse")
          i -= 1
    
  • Nous pouvons également utiliser une boucle for, où nous pouvons faire quelque chose pour chaque élément d'une liste :

      for i in [0, 1, 2]:
          print("tousse")
    
    • Les listes en Python sont comme les tableaux en C, mais elles peuvent facilement grandir et rétrécir, l'interpréteur gérant pour nous l'implémentation et la mémoire.
    • Cette boucle for définira la variable i sur le premier élément, 0, s'exécutera, puis sur le deuxième élément, 1, s'exécutera, etc.
    • Et nous pouvons utiliser une fonction spéciale, range, pour obtenir un certain nombre de valeurs, comme dans for i in range(3). Cela nous donnera 0, 1 et 2, pour un total de trois valeurs.
  • En Python, il existe de nombreux types de données :

    • bool, True ou False
    • float, nombres réels
    • int, des entiers
    • str, des chaînes
    • range, une séquence de nombres
    • list, une séquence de valeurs modifiables, que nous pouvons modifier, ajouter ou supprimer
    • tuple, une séquence de valeurs immuables, que nous ne pouvons pas modifier
    • dict, une collection de paires clé/valeur, comme une table de hachage
    • set, une collection de valeurs uniques
  • docs.python.org est la source officielle de documentation, mais Google et StackOverflow disposeront également de ressources utiles lorsque nous aurons besoin de savoir comment faire quelque chose en Python. En fait, les programmeurs dans le monde réel connaissent rarement tout ce qui est dans la documentation, mais plutôt comment trouver ce dont ils ont besoin quand ils en ont besoin.

Exemples

  • On peut flouter une image avec :

      from PIL import Image, ImageFilter
    
      before = Image.open("pont.bmp")
      after = before.filter(ImageFilter.BLUR)
      after.save("out.bmp")
    
    • En Python, on inclut d’autres bibliothèques avec import, et ici on va import les noms Image et ImageFilter depuis la bibliothèque PIL.
    • En fait, si on cherche la documentation pour la bibliothèque PIL, on peut utiliser les trois lignes de code suivantes pour ouvrir une image appelée pont.bmp, appliquer un filtre de flou dessus et l’enregistrer dans un fichier appelé out.bmp.
    • Et on peut exécuter ça avec python flou.py après avoir enregistré dans un fichier appelé flou.py.
  • On peut implémenter un dictionnaire avec :

      mots = set()
    
      def vérifier(mot):
          if mot.lower() in mots:
              return True
          else:
              return False
    
      def charger(dictionnaire):
          fichier = open(dictionnaire, "r")
          pour chaque ligne dans fichier:
              mots.add(ligne.rstrip("\n"))
          fichier.close()
          return True
    
      def taille():
          return len(mots)
    
      def décharger():
          return True
    
    • D’abord, on crée un nouvel ensemble nommé mots. Ensuite, pour vérifier, on peut juste demander if mot.lower() in mots. Pour charger, on ouvre le fichier et on utilise mots.add pour ajouter chaque ligne à notre ensemble. Pour taille, on peut utiliser len pour compter le nombre d’éléments dans notre ensemble, et enfin, pour décharger, on n’a rien à faire !
  • Il s'avère que, même si l'implémentation d'un programme en Python est plus simple pour nous, le temps d'exécution de notre programme en Python est plus lent que notre programme en C puisque notre interpréteur doit faire plus de travail pour nous. Donc, en fonction de nos objectifs, nous devrons également prendre en compte le compromis du temps humain d'écriture d'un programme plus efficace, par rapport au temps d'exécution du programme.

  • En Python, nous pouvons aussi inclure la bibliothèque CS50, mais notre syntaxe sera :

      from cs50 import get_string
    
    • Notez que nous spécifions les fonctions que nous voulons utiliser.
  • Maintenant, nous pouvons obtenir des chaînes d'un utilisateur :

      from cs50 import get_string
    
      s = get_string("Comment vous appelez-vous ? :\n")
      print("bonjour, " + s)
    
  • Nous pouvons aussi substituer des expressions dans nos chaînes de format :

      from cs50 import get_int
    
      age = get_int("Quel âge avez-vous ?\n")
      print(f"Vous avez au moins {age * 365} jours.")
    
  • Et nous pouvons montrer des conditions :

      from cs50 import get_int
    
      x = get_int("x : ")
      y = get_int("y : ")
    
      if x < y:
          print("x est inférieur à y")
      elif x > y:
          print("x est supérieur à y")
      else:
          print("x est égal à y")
    
  • Pour vérifier des conditions, nous pouvons dire :

      from cs50 import get_string
    
      s = get_string("Êtes-vous d'accord ?\n")
    
      if s == "O" ou s == "o":
          print("D'accord.")
      elif s == "N" ou s == "n":
          print("Pas d'accord.")
    
    • Python n'a pas de caractères, donc nous pouvons les vérifier directement en tant que chaînes.
    • Nous pouvons également dire if s in ["O", "o"]:, ou if s.lower() in ["o"]:. Il s'avère que les chaînes en Python sont comme des structs en C, où nous avons non seulement des variables mais aussi des fonctions que nous pouvons appeler. Par exemple, étant donné une chaîne s, nous pouvons appeler sa fonction lower avec s.lower() pour obtenir la version minuscule de la chaîne.
  • Nous pouvons également améliorer les versions de cough :

      print("cough")
      print("cough")
      print("cough")
    
    • Nous n'avons pas besoin de déclarer une fonction main, nous écrivons donc simplement la même ligne de code trois fois.
  • Mais nous pouvons faire mieux :

      for i in range(3):
          cough()
    
      def cough():
          print("cough")
    
    • Notez que nous n'avons pas besoin de spécifier le type de retour d'une nouvelle fonction, que nous pouvons définir avec def.
    • Mais cela provoque une erreur lorsque nous essayons de l'exécuter : NameError : le nom 'cough' n'est pas défini. Il s'avère que nous devons définir notre fonction avant de l'utiliser, nous pouvons donc soit déplacer notre définition de cough vers le haut, soit créer une fonction main :

        def main():
            for i in range(3):
                cough()
      
        def cough():
            print("cough")
      
        main()
      
    • Désormais, au moment où nous appelons notre fonction main, la fonction cough aura été lue par notre interprète.

  • Nos fonctions peuvent également prendre des entrées :

      def main ():
          cough(3)
    
      def cough(n ):
          for i in range(n ):
              print("toux")
    
      main()
    
  • Nous pouvons définir une fonction pour obtenir un entier positif :

      from cs50 import get_int
    
      def main ():
          i = get_positive_int()
          print(i)
    
      def get_positive_int ():
          while True :
              n = get_int("Entier positif : ")
              if n > 0 :
                  break
          return n
    
      main()
    
  • Comme il n’y a pas de boucle do-while en Python comme en C, on utilise une boucle while qui continue à l’infini et on utilise break pour quitter la boucle dès que n > 0. Ensuite, notre fonction retourne simplement n.

  • Remarquez que les variables en Python ont une portée de fonction par défaut, ce qui signifie que n peut être initialisé dans une boucle et toujours accessible plus tard dans la fonction.

  • Nous pouvons afficher une ligne de points d’interrogation à l’écran :

      for i in range(4 ):
          print("?", end="")
      print()
    
  • Lorsque nous imprimons chaque bloc, nous ne voulons pas de nouvelle ligne automatique. Nous pouvons donc passer un paramètre ou un argument nommé à la fonction print. Ici, nous disons end="" pour spécifier que rien ne doit être imprimé à la fin de notre chaîne. Ensuite, après avoir imprimé notre ligne, nous pouvons appeler print pour obtenir une nouvelle ligne.

  • Nous pouvons également « multiplier » une chaîne de caractères et l'afficher directement avec : print("?" * 4).

  • Nous pouvons afficher une colonne avec une boucle :

      for i in range(3):
          print("#")
    
  • Et sans boucle : print("#\n" * 3, end="").

  • Nous pouvons implémenter des boucles imbriquées :

      for i in range(3):
          for j in range(3):
              print("#", end="")
          print()
    
  • Nous n'avons pas besoin d'utiliser la fonction get_string de la bibliothèque CS50 ; nous pouvons simplement utiliser la fonction input intégrée à Python pour obtenir une chaîne de caractères de l'utilisateur. Mais si nous voulons obtenir un autre type de donnée, comme un entier, de l'utilisateur, nous devrons le « caster » avec int().

  • Mais notre programme plantera si la chaîne de caractères ne peut pas être convertie en un entier ; nous pouvons donc utiliser get_string qui redemandera simplement la saisie.
  • En Python, essayer de dépasser la capacité d'un entier ne fonctionnera pas :

      from time import sleep
    
      i = 1
      while True:
          print(i)
          sleep(1)
          i *= 2
    
    • Nous appelons la fonction sleep pour mettre notre programme en pause pendant une seconde entre chaque itération.
    • Cela continuera jusqu'à ce que l'entier ne puisse plus tenir dans la mémoire de votre ordinateur.
  • L'imprécision en virgule flottante peut également être évitée grâce à des bibliothèques qui peuvent représenter des nombres décimaux avec autant de bits que nécessaire.

  • Nous pouvons créer une liste :

      scores = []
      scores.append(72)
      scores.append(73)
      scores.append(33)
    
      print(f"Moyenne : {sum(scores) / len(scores)}")
    
    • Avec append, nous pouvons ajouter des éléments à notre liste en l'utilisant comme une liste chaînée.
    • Nous pouvons également déclarer une liste avec certaines valeurs, comme scores = [72, 73, 33].
  • Nous pouvons itérer sur chaque caractère d'une chaîne de caractères :

      from cs50 import get_string
    
      s = get_string("Entrée : ")
      print("Sortie : ", end="")
      for c in s:
          print(c, end="")
      print()
    
    • Python obtiendra chaque caractère de la chaîne pour nous.
  • Pour mettre une chaîne de caractères en majuscules, nous pouvons également simplement appeler s.upper() pour obtenir la version en majuscules de la chaîne entière, sans avoir à itérer nous-mêmes sur chaque caractère.

Plus de fonctionnalités

  • On peut prendre des arguments de ligne de commande avec :

      from sys import argv
    
      for i in range(len(argv)):
          print(argv[i])
    
    • Puisque argv est une liste de chaînes de caractères, on peut utiliser len() pour obtenir sa longueur, et range() pour obtenir une plage de valeurs que l'on peut utiliser comme index pour chaque élément de la liste.
  • Mais on peut aussi laisser Python itérer sur la liste pour nous :

      from sys import argv
    
      for arg in argv:
          print(arg)
    
  • On peut aussi retourner des codes de sortie lorsque notre programme se termine :

      from sys import argv, exit
    
      if len(argv) != 2:
          print("argument de ligne de commande manquant")
          exit(1)
      print(f"bonjour, {argv[1]}")
      exit(0)
    
    • On importe la fonction exit, et on l'appelle avec le code avec lequel on souhaite que le programme se termine.
  • On peut implémenter une recherche linéaire en vérifiant simplement chaque élément d'une liste :

      import sys
    
      names = ["EMMA", "RODRIGO", "BRIAN", "DAVID"]
    
      if "EMMA" in names:
          print("Trouvé")
          sys.exit(0)
      print("Non trouvé")
      sys.exit(1)
    
  • Si nous avons un dictionnaire, un ensemble de paires clé:valeur, nous pouvons également vérifier chaque clé :

      import sys
    
      people = {
          "EMMA": "617-555-0100",
          "RODRIGO": "617-555-0101",
          "BRIAN": "617-555-0102",
          "DAVID": "617-555-0103"
      }
    
      if "EMMA" in people:
          print(f"Trouvé {people['EMMA']}")
          sys.exit(0)
      print("Introuvable")
      sys.exit(1)
    
    • Notez que nous pouvons obtenir la valeur d'une clé particulière dans un dictionnaire avec people['EMMA']. Ici, nous utilisons des guillemets simples (les guillemets simples et doubles sont autorisés, tant qu'ils correspondent à une chaîne) pour différencier la chaîne interne de la chaîne externe.
    • Et nous déclarons des dictionnaires avec des accolades, {}, et des listes avec des crochets [].
  • En Python, nous pouvons comparer des chaînes directement avec juste == :

      from cs50 import get_string
    
      s = get_string("s: ")
      t = get_string("t: ")
    
      if s == t:
          print("Identique")
      else:
          print("Différent")
    
  • Copier des chaînes fonctionne aussi sans aucun travail supplémentaire de notre part :

      from cs50 import get_string
    
      s = get_string("s: ")
    
      t = s
    
      t = t.capitalize()
    
      print(f"s: {s}")
      print(f"t: {t}")
    
  • L'échange de deux variables peut également se faire en attribuant les deux valeurs en même temps :

      x = 1
      y = 2
    
      print(f"x vaut {x}, y vaut {y}")
      x, y = y, x
      print(f"x vaut {x}, y vaut {y}")
    

Fichiers

  • Ouvrons un fichier CSV :

      import csv
      from cs50 import get_string
    
      file = open("phonebook.csv", "a")
    
      name = get_string("Nom : ")
      number = get_string("Numéro : ")
    
      writer = csv.writer(file)
      writer.writerow((name, number))
    
      file.close()
    
  • Il s'avère que Python dispose également d'un package (bibliothèque) csv qui nous aide à travailler avec les fichiers CSV. Ainsi, après avoir ouvert le fichier pour l'ajout, nous pouvons appeler csv.writer pour créer un writer à partir du fichier, puis writer.writerow pour écrire une ligne. Avec les parenthèses internes, nous créons un tuple avec les valeurs que nous voulons écrire. Nous faisons donc passer un seul argument qui contient toutes les valeurs de notre ligne.

  • Nous pouvons utiliser le mot-clé with qui fermera le fichier à notre place :

      ...
      with open("phonebook.csv", "a") as file:
          writer = csv.writer(file)
          writer.writerow((name, number))
    

Nouvelles fonctionnalités

  • Une fonctionnalité de Python que C ne possède pas est celle des expressions régulières, ou motifs sur lesquels nous pouvons faire correspondre des chaînes. Par exemple, sa syntaxe comprend :
    • ., pour n'importe quel caractère
    • .*, pour 0 caractère ou plus
    • .+, pour 1 caractère ou plus
    • ?, pour une option
    • ^, pour le début de la saisie
    • $, pour la fin de la saisie
  • Par exemple, nous pouvons faire correspondre des chaînes avec :

      import re
      from cs50 import get_string
    
      s = get_string("Êtes-vous d'accord  ?\n")
    
      if re.search("^y(es)?$", s, re.IGNORECASE):
          print("D'accord.")
      elif re.search("^no?$", s, re.IGNORECASE):
          print("Pas d'accord.")
    
    • Tout d'abord, nous avons besoin du package, ou bibliothèque, re pour les expressions régulières.
    • Ensuite, pour y ou yes, nous avons l'expression régulière ^y(es)?$. Nous voulons nous assurer que la chaîne commence par y et qu'elle est éventuellement suivie par es juste après y, puis qu'elle se termine.
    • De même, pour n et no, nous voulons que notre chaîne commence par la lettre n, qu'elle soit éventuellement suivie par la lettre o, puis qu'elle se termine. L'expression régulière pour cela serait ^no?$.
    • Nous transmettons un autre argument, re.IGNORECASE, pour ignorer les majuscules et minuscules dans la chaîne.
    • Si aucune expression régulière ne correspond, nous n'imprimons rien.
  • Sur notre propre Mac ou PC, nous pouvons ouvrir un terminal après l'installation de Python, et utiliser le micro pour convertir notre discours en texte :

      import speech_recognition
    
      recognizer = speech_recognition.Recognizer()
      with speech_recognition.Microphone() as source:
          print("Dites quelque chose !")
          audio = recognizer.listen(source)
    
      print("Google Speech Recognition pense que vous avez dit :")
      print(recognizer.recognize_google(audio))
    
    • Il s'avère qu'il existe une autre bibliothèque que nous pouvons télécharger, appelée speech_recognition, qui permet d'écouter l'audio et de le convertir en chaîne de caractères.
  • Et maintenant, nous pouvons comparer l'audio pour imprimer autre chose :

      ...
      words = recognizer.recognize_google(audio)
    
      # Répondre au discours
      if "hello" in words:
          print("Hello to you too!")
      elif "how are you" in words:
          print("I am well, thanks!")
      elif "goodbye" in words:
          print("Goodbye to you too!")
      else:
          print("Huh?")
    
  • Nous pouvons même utiliser des expressions régulières, pour comparer une partie d'une chaîne :

      ...
      words = recognizer.recognize_google(audio)
    
      matches = re.search("my name is (.*)", words)
      if matches:
          print(f"Hey, {matches[1]}.")
      else:
          print("Hey, you.")
    
    • Ici, nous pouvons obtenir tous les caractères après my name is avec .*, and les imprimer.
  • Nous exécutons detect.py et faces.py, qui trouve chaque visage (ou même un visage spécifique) sur une photo.

  • qr.py créera également un code QR vers une URL particulière.