Aller au contenu

Introduction au langage python

I - Variables⚓︎

Une variable* est une "boîte" dans laquelle on va stocker une donnée afin que le programme puisse y accéder au besoin.
Cela peut être le résultat d'un calcul, un numéro de téléphone, du texte, et même des images, de la musique...

Pour affecter la valeur 1789 à la variable revolution, puis la valeur 1492 à la variable amerique et enfin caculer le temps écoulé entre les 2 dates, il suffit décrire ceci:

🐍 Script Python
>>> revolution = 1789
>>> amerique = 1492
>>> revolution - amerique
297

II - Types⚓︎

On l'a vu dans le chapitre précédent, il existe plusieurs façon d'écrire un nombre, selon qu'il soit entier ou décimal.
Ainsi un nombre entier aura le type int tandis qu'un nombre décimal aura le type float. Il est bien entendu possible d'attribuer le type float à un nombre entier, mais l'inverse aboutira à la troncature du nombre décimal :

🐍 Script Python
>>> float(10)
10.0

>>> int(2.53)
2

On remarque que le passage d'un type int vers un type float se traduit par l'écriture d'un .0 à la fin du nombre.
C'est ainsi que a=10 affectera automatiquement le type int à a mais que a=10.0 affectera le type float.

Il y a d'autres types, notamment string pour les chaînes de caractère

III - Conditions⚓︎

Les tests logiques vus au précédent chapitre peuvent être utilisés pour adapter le comportement d'un problème aux données qu'il reçoit.
Cela va se traiter avec la structure conditionnelle

🐍 Script Python
if (condition) :
    ...(instructions)
elif (condition) :
    ...(instructions)
else :
    ...(instructions)

Attention ! Le test d'égalité s'écrit a==b car le simple = est un opérateur d'attribution (il stockera la valeur de droite dans la variable de gauche).

IV - Boucles⚓︎

Lorsque l'on doit executer un certain nombre de fois un travail similaire, on peut utiliser une boucle. Il y a 2 types différents : while (condition): ("tant que") et for i in ... : ("pour").
Généralement, on utilise la boucle while lorsque l'on ne connaît pas à l'avance le nombre d'itérations, et la boucle for pour balayer un ensemble prédéterminé.
Dans les 2 cas, il n'est pas nécessaire que la condition porte sur des nombres.

Exemple :afficher tous les nombres entre 1 et 100

🐍 Script Python
# avec while
i=1
while i < 101:
    print(i)
    i+=1

# avec for
for i in range(1,101):
    print(i)

V - Les tuples, les listes et dictionnaires⚓︎

Cliquer pour voir les activités de présentation :

1- Tuples et listes⚓︎

a. Présentation⚓︎

Ces 2 objets ont un fonctionnement proche : on accède à un élément en utilisant la syntaxe liste[n] et on détermine le nombre d'élément qui le composent avec len(liste).
En revanche un tuple s'écrira mon_tuple=(1,2,3) tandis qu'une liste s'écrira ma_liste=[1,2,3].
Enfin, un tuple est non mutable ce qui signifie que vous ne pourrez pas modifier ses éléments :

Exemple :afficher tous les nombres entre 1 et 100

🐍 Script Python
>>> mon_tuple=(1,2,3)
>>> mon_tuple[1]=0
Traceback (most recent call last):

  File "<ipython-input-4-52816df946e1>", line 1, in <module>
    mon_tuple[1]=0

TypeError: 'tuple' object does not support item assignment

b. Construire une liste⚓︎

En dehors de l'attribution, il est possible de construire une liste par concaténation :

🐍 Script Python
>>> a=[1,2,3]+[4,5,6]
>>> a
[1, 2, 3, 4, 5, 6]

Il est également possible d'utiliser .append():

🐍 Script Python
>>> a=[1,2,3]+[4,5,6]
>>> a.append(7)
>>> a
[1, 2, 3, 4, 5, 6, 7]

Il est possible de coupler ces méthodes avec une boucle, de 3 façons :

Créer une liste contenant les 100 premiers multiples de 7

🐍 Script Python
multiples=[]
for i in range(100):
    multiples+=[7*i]
🐍 Script Python
multiples=[]
for i in range(100):
    multiples.append(7*i)
🐍 Script Python
multiples=[7*i for i in range(100)]

c. Parcourir une liste/un tuple⚓︎

Pour ne prendre en compte qu'une partie d'une liste, il suffit de le préciser dans les crochets (on appelle cela slice [tranche en anglais]):

🐍 Script Python
>>> a=[1,2,3,4,5,6,7,8,9]
>>> a[2:7]
[3, 4, 5, 6, 7]
>>> a[:8]
[1, 2, 3, 4, 5, 6, 7, 8]
>>> a[5:]
[6, 7, 8, 9]
>>> a[-3:-1]
[7, 8]
>>> a[::2]
[1,3,5,7,9]
>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

La première position correspond au point de départ et la seconde à la position suivant le dernier item. La troisième information indique le pas ainsi que le sens de lecture de liste, en indiquant [x:y:2] on indique qu'on lit la liste de deux en deux et avec [::-1] la totalité de la liste est lue à l'envers !

Ces commandes fonctionnent également avec les chaînes de caractères !

🐍 Script Python
>>> "et c'est très pratique !"[::-1]
"! euqitarp sèrt tse'c te"

d. Effacer un terme⚓︎

Pour effacer un(des) terme(s) d'une liste (ou la liste entière), on utilise la commande del.

🐍 Script Python
>>> a=[1,2,3,4,5,6,7,8,9]
>>> del(a[3])
>>> a
[1, 2, 3, 5, 6, 7, 8, 9]
>>> del(a[3:5])
>>> a
[1, 2, 3, 7, 8, 9]
>>> del(a[:])
>>> a
[]
>>> del(a)
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

2- Les dictionnaires⚓︎

a. Créer un dictionnaire⚓︎

Comme vous l'avez découvert dans l'activité d'introduction, un dictionnaire a une structure différente de celle des listes. Les valeurs ne sont plus rangées en fonction d'un indice (valeur numérique entière) mais à l'aide de clés (chaîne de caractère).

Pour créer un dictionnaire, on peut soit le définir directement :

🐍 Script Python
>>> mon_dictionnaire={"age":36,"nom":"Duplant","prénom":"Christophe"}
>>> mon_dictionnaire
{'age': 36, 'nom': 'Duplant', 'prénom': 'Christophe'}

soit ajouter des informations de façon plus classique :

🐍 Script Python
>>> mon_dictionnaire["telephone"]="0601020304"
>>> mon_dictionnaire
{'age': 36, 'nom': 'Duplant', 'prénom': 'Christophe', 'telephone' : "0601020304"}

b. Parcourir un dictionnaire⚓︎

Pour accéder à la valeur associée à une clé d'un dictionnaire :

🐍 Script Python
>>> mon_dictionnaire["nom"]
'Duplant'

Pour avoir la liste de toutes les clés présentes dans un dictionnaire :

🐍 Script Python
>>> mon_dictionnaire.keys()
dict_keys(['age', 'nom', 'prénom', 'telephone'])

Pour afficher toutes les valeurs associées à chaque clé du dictionnaire :

🐍 Script Python
>>> mon_dictionnaire["nom"]
'Duplant'

Pour avoir la liste de toutes les clés présentes dans un dictionnaire :.

🐍 Script Python
>>> mon_dictionnaire.keys()
dict_keys(['age', 'nom', 'prénom', 'telephone'])
>>> for i in mon_dictionnaire.keys():
        print(i,mon_dictionnaire[i])    
age 36
nom Duplant
prénom Christophe
telephone 0601020304

Pour savoir si une clé est présente dans le dictionnaire :

🐍 Script Python
>>> "prénom" in mon_dictionnaire.keys()
True
>>> "voiture" in mon_dictionnaire.keys()
False
Faire la fiche 07

Cliquer ici pour récupérer le document

Corrigé de la dernière partie (cliquer sur 'lancer' pour voir le résultat)

###



VI- Les modules⚓︎

1- Présentation⚓︎

Les modules permettent de réaliser certaines opération par défaut impossible ou d'éviter d'avoir à coder de nouveau certaines fonctions utiles.

On utilise par exemple régulièrement les modules math ou random.

Chaque module contient plusieurs fonctions que l'on pourra utiliser une fois le module importé.

🐍 Script Python
import math

math.sin(math.pi/4)
0.7071067811865476
Ici, seul le module est importé et il faut alors préciser que l'on appelle la fonction *sin()* du module math.
🐍 Script Python
from math import sin,pi

sin(pi/4)
0.7071067811865476
Dans ce cas, seules les fonctions indiquées sont importées, sans avoir à préciser le préfixe *math.*.

2- Les modules sur calculatrice Numworks⚓︎

Afin de pouvoir travailler avec des images, la calculatrice Numworks intègre le module kandinsky (cliquez pour accéder au manuel).
Ce module, très simple, permet de dessiner des points, du texte et des rectangles.

A faire

En utilisant votre calculatrice ou l'émulateur officiel, saisir le code suivant et l’exécuter :

🐍 Script Python
from kandinsky import *
for i in range(256):
    for j in range(256):
        set_pixel(i,j,(i,j,511-(i+j)))

A faire

En vous basant sur ce script, ainsi que la documentation représenter les drapeaux français, italien et allemand

Corrigé
🐍 Script Python
from kandinsky import *
def france():
for i in range(320):
    for j in range(220):
    if i < (320/3):
        set_pixel(i,j,(0,0,255))
    elif i < (2*320/3):
        set_pixel(i,j,(255,255,255))
    else :
        set_pixel(i,j,(255,0,0))

def italie():
for i in range(320):
    for j in range(220):
        if i<(320/3):
            set_pixel(i,j,(0,255,0))
        elif i<(2*320/3):
            set_pixel(i,j,(255,255,255))
        else :
            set_pixel(i,j,(255,0,0))

def allemagne():
for i in range(320):
    for j in range(220):
        if j < (220/3):
            set_pixel(i,j,(0,0,0))
        elif j < (2*220/3):
            set_pixel(i,j,(255,255,0))
        else :
            set_pixel(i,j,(255,0,0))

A faire

Utiliser la fonction fill_rect(x,y,largeur,hauteur,(r,v,b)) pour faire la même chose, mais sans avoir à faire de boucle. Que remarquez-vous ?

Corrigé
🐍 Script Python
from kandinsky import *
def rec_france():
fill_rect(0,0,320//3,220,(0,0,255))
fill_rect(320//3,0,2*320//3,220,(255,255,255))
fill_rect(2*320//3,0,320,220,(255,0,0))

def rec_italie():
fill_rect(0,0,320//3,220,(0,255,0))
fill_rect(320//3,0,2*320//3,220,(255,255,255))
fill_rect(2*320//3,0,320,220,(255,0,0))

def rec_allemagne():
fill_rect(0,0,320,220//3,(0,0,0))
fill_rect(0,220//3,320,2*220//3,(255,255,0))
fill_rect(0,2*220//3,320,220,(255,0,0))

On remarque que l'affichage des drapeaux est quasi instantané cette fois.

A faire

A l’aide d’une boucle while( ) du type :

🐍 Script Python
while True :
    commandes
Dessiner un rectangle dont la couleur oscille du rouge (255,0,0) au vert (0,255,0).

Corrigé
🐍 Script Python
from kandinsky import *
def oscillation():
    valeur=0
    while True:
        fill_rect(0,0,320,220,(255-valeur,valeur,0))
        valeur=(valeur+1)%256

On réalise une boucle sans fin qui va dessiner un rectangle initialement rouge (255,0,0) puis qui va évoluer vers le vert (254,1,0),(253,2,0),...,(0,255,0).

Pour ne pas dépasser la valeur 255 on utilise le modulo qui repassera valeur à 0 une fois que 256 sera atteint.

A faire

a. Écrire une fonction bouge(vitx,vity) qui dessine un rectangle se déplaçant à l’écran avec une vitesse verticale vity et une vitesse horizontale vitx b. La fonction s’arrête lorsque le rectangle sort de l’écran c. Le rectangle rebondit lorsqu’il "touche" le bord de l’écran

Corrigé
🐍 Script Python
from kandinsky import *
def bouge1(vitx,vity,posx,posy):
    while True:
        fill_rect(posx,posy,10,10,(255,255,255))
        posx+=vitx
        posy+=vity
        fill_rect(posx,posy,10,10,(255,0,0))

a. La fonction bouge1 utilise comme paramètres d'entrée la vitesse selon x et y (vitx et vity) ainsi que la position initiale de l'objet (posx et posy).
Il execute ensuite une boucle qui ne s'arrête pas, qui commence par "effacer" le rectangle en dessinant un carré blanc à la place, puis incrémente la position en y ajoutant la vitesse et enfin dessine le rectangle à la nouvelle position.

On a alors la sensation que le rectangle s'est déplacé.

🐍 Script Python
def bouge2(vitx,vity,posx,posy):
    while not(posx<0 or posy<0 or posx>(320-10) or posy>(220-10)):
        fill_rect(posx,posy,10,10,(255,255,255))
        posx+=vitx
        posy+=vity
        fill_rect(posx,posy,10,10,(255,0,0))
b. La fonction bouge2 est presque identique à bouge1 si ce n'est que la boucle while vérifie que le rectangle se dessine bien dans l'écran qui a une définition de 320 pixels en largeur et 220 en hauteur.

On arrête la fonction 10 pixels avant d'arriver à droite (320-10 ou en bas (220-10) afin que le rectangle s'arrête dès qu'il "touche" la bordure.

🐍 Script Python
def bouge3(vitx,vity,posx,posy):
    while True:
        if posx<0 or posx>(320-10):
            vitx=-vitx
        if posy<0 or posy>(220-10):
            vity=-vity
        fill_rect(posx,posy,10,10,(255,255,255))
        posx+=vitx
        posy+=vity
        fill_rect(posx,posy,10,10,(255,0,0))

c. Ici la boucle ne s'arrête plus. En revanche 2 conditions sont ajoutées : lorsque le rectangle "touche" les bordures horizontales, il rebondit : on inverse alors vitx. De même avec les bordure verticale où l'on inverse vity.

On remarque que même avec des vitesses faibles (par exemple bouge3(1,1,10,10) où le rectangle ne se déplacera que d'1 pixel par boucle) le rectangle se déplace très vite. Pour le ralentir, il est dès lors nécessaire d'utiliser une temporisation pour le ralentir, d'où la question ci-dessous.

A faire

Utiliser les modules time et ion pour faire bouger le rectangle à l’aide du clavier de la calculatrice

Corrigé
🐍 Script Python
from time import sleep
def bouge4(vitesse,vitx,vity,posx,posy):
    while True:
        if posx<0 or posx>(320-10):
            vitx=-vitx
        if posy<0 or posy>(220-10):
            vity=-vity
        fill_rect(posx,posy,10,10,(255,255,255))
        posx+=vitx
        posy+=vity
        fill_rect(posx,posy,10,10,(255,0,0))
        sleep(1/vitesse)

La fonction sleep(x) présente dans le module ion arrête la fonction pendant x seconde.

En ajoutant sleep(1/vitesse) on fait donc en sorte de rendre l'arrêt d'autant plus court que vitesse est grand.

🐍 Script Python
from ion import *
def bouge5():
    posx,posy=160,110
    vitesse=3
    while True:
        if posx<0 or posy<0 or posx>(320-10) or posy>(220-10):
            print("Perdu !")
            return False
        fill_rect(posx,posy,10,10,(255,255,255))
        if keydown(KEY_LEFT):
            posx-=1
        if keydown(KEY_RIGHT):
            posx+=1
        if keydown(KEY_UP):
            posy-=1
        if keydown(KEY_DOWN):
            posy+=1
        if keydown(KEY_PLUS):
            vitesse+=1
        if keydown(KEY_MINUS):
            vitesse-=1
        fill_rect(posx,posy,10,10,(255,0,0))
        sleep(1/vitesse)

Le module ion contient la fonction keydown(touche) qui indique si la touche est en train d'être pressée.

Ici on choisit de ne modifier la position du rectangle que lorsque les touches de direction sont pressées. les touches "+" et "-" sont utilisées pour modifier la valeur de vitesse, comme dans la fonction bouge4().

Danger

La totalité des fonctions est présente sur mon espace Numworks : Cliquer ici.

Il vous suffit donc de connecter votre calculatrice à votre ordinateur pour y envoyer toutes les fonctions !

3- Manipuler des fichiers⚓︎

a. Ouvrir/lire/écrire dans un fichier⚓︎

On va pouvoir ouvrir un fichier en mode texte à l'aide de la fonction open()

Pour ouvrir le fichier mon_texte.txt se trouvant dans le dossier C:\python :

🐍 Script Python
with open("C:/python/mon_texte.txt","r",encoding="utf-8") as txt :
    le_texte = txt.read()
print(le_texte)
>>> %Run lecture.py
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
Maître Renard, par l'odeur alléché,
Lui tint à peu près ce langage :
  • with open(...) as ... : permet d'ouvrir un fichier et de le traiter.
  • A l'intérieur du bloc with on écrit les commandes que l'on souhaite réaliser sur le texte alors stocké dans la variable txt mais pas utilisable en tant que chaîne de caractères
  • open(...) accepte 3 modes de traitement du fichier : "r" pour le lire, "a" pour ajouter du texte à la suite de ce qui y est déjà et "w" pour le créer ou le réécrire en effaçant ce qui s'y trouvait
  • la méthode qui transforme le texte en chaine de caractères est txt.read(). Si l'on souhaite transformer le texte en une liste de chaines de caractères où chaque item de la liste est une ligne du texte, on peut utiliser text.readlines() à la place.

Example

Le fichier mon_texte.txt contient la fable Le corbeau et le renard de Jean de La Fontaine. Une fois téléchargé et enregistré dans le répertoire c:\python, on souhaite éditer le texte et écrire toutes les voyelles en majuscule.

Corrigé
🐍 Script Python
with open("C:/python/mon_texte.txt", "r", encoding="utf-8") as txt :
    texte = txt.read()
texte_modifie = ""
for lettre in texte:
    if lettre in "aeiouy":
        texte_modifie += chr(ord(lettre) - (97 - 65))
    else:
        texte_modifie += lettre            
with open("C:/python/mon_texte_modifie.txt", "w", encoding="utf-8") as resultat :
    le_nouveau_texte.write(texte_modifie)

Si vous avez enregistré le fichier au bon endroit et que les droits en écriture ont été accordés par le système à votre interpréteur python, vous devriez voir apparaître un fichier mon_texte_modifie.txt dans lequel toutes les voyelles non accentuées ont été basculées en majuscules.

Ce que fait ce script :

  • Il ouvre le fichier mon_texte.txt, puis à l'aide de la méthode .read() va enregistrer le texte dans la variable texte
  • On crée ensuite la chaîne texte_modifie qui comme son nom l'indique va accueillir le texte modifié.
  • on parcourt texte caractère par caractère. Si un caractère appartient à "aeiouy", c'est une voyelle minuscule : on la bascule donc en majuscule en modifiant son code ascii de 97-65, soit la valeur qui sépare le A du a dans la table ascii
  • on ajoute chaque caractère, modifié le cas échéant, dans texte_modifie
  • enfin ouvre le nouveau fichier mon_texte_modifie.txt avec l'attribut "w" : si le fichier n'existe pas il sera créé, sinon il sera réécrit.
  • on y écrit la chaîne le_texte_modifie

4- Se simplifier la vie avec le module tkinter⚓︎

Il est parfois difficile ou rébarbatif d'écrire le chemin d'accès complet au fichier.

Cette fonction, utilisant le module tkinter pour faire apparaître une fenêtre de sélection vous simplifiera la vie !

🐍 Script Python
from tkinter import filedialog,Tk

def fichier(action):
    popup=Tk()
    if action=="ouvrir":
        chemin_fichier =  filedialog.askopenfilename(initialdir = "./",title = "Select file")
    elif action=="enregistrer":
        chemin_fichier =  filedialog.asksaveasfilename(initialdir = "./",title = "Select file")
    else:
        chemin_fichier=False
    popup.destroy()
    return chemin_fichier

la fonction fichier(action) vous permet donc d'ouvrir ou de choisir où enregistrer votre fichier.

Pour l'exercice précédent (la fable du corbeau et du renard), il suffit donc d'écrire :

Corrigé modifié
🐍 Script Python
from tkinter import filedialog,Tk

def fichier(action):
    popup=Tk()
    if action=="ouvrir":
        chemin_fichier =  filedialog.askopenfilename(initialdir = "./",title = "Select file")
    elif action=="enregistrer":
        chemin_fichier =  filedialog.asksaveasfilename(initialdir = "./",title = "Select file")
    else:
        chemin_fichier=False
    popup.destroy()
    return chemin_fichier

with open(fichier("ouvrir"),"r",encoding="utf-8") as le_texte:
    texte = le_texte.read() 

texte_modifie=""

for lettre in texte:
    if lettre in "aeiouy":
        texte_modifie+=chr(ord(lettre)-(97-65))
    else:
        texte_modifie+=lettre

with open(fichier("enregistrer"),"w",encoding="utf-8") as le_nouveau_texte :
    le_nouveau_texte.write(texte_modifie)

5- Traiter les images avec le module pillow⚓︎

a. Charger une image⚓︎

Remarque :

Toute la partie sera traitée avec image_PIL.jpg cette image. Enregistrez-là pour avoir les mêmes résultats que moi. (une barre de chocolat à qui en identifie le lieu).

Toute image est stockée numériquement sous forme binaire. Chaque format d'image a une façon particulière de s'écrire. Pour simplifier leur prise en charge, le module pillow va ouvrir l'image et l'interpréter sous la forme d'un tableau (x,y) dans lequel la couleur correspondant à chaque pixel sera présente. Pour l'utiliser avec la fonction fichier(action) écrite précédemment :

🐍 Script Python
>>>from PIL import Image
>>>mon_image=Image.open(fichier("ouvrir"))
>>>mon_image.size
(3968, 2976)
>>>mon_image.getpixel((200,200))
(145, 150, 169)

mon_image.size donne les dimensions (x,y) de l'image, mon_image.getpixel((x,y)) indique le code couleur du pixel indiqué.

Enfin, mon_image.putpixel((x,y),(r,v,b)) coloriera le pixel de coordonnées (x,y) à la couleur (r,v,b).

mon_image.show() affichera l'image et mon_image.save("dossier/image.jpg") permettra de l'enregistrer. C'est l'extension (jpg,bmp,png) qui permettra à PIL de connaître la norme d'encodage dans laquelle il doit l'enregistrer, n'oubliez donc pas que jpg enregistre à perte !

b. Créer une image⚓︎

PIL permet également de créer une image, en indiquant ses dimensions (largeur,longueur) ainsi que le type de couleur :

  • "1" pour une image en noir et blanc, chaque pixel prenant la valeur 0 ou 1.
  • "L" pour une image en niveaux de gris, chaque pixel prenant une valeur entière entre 0 (noir) et 255 (blanc)
  • "RGB" pour une image en couleur, chaque pixel prenant un tuple (r,v,b) chaque composante étant un nombre entier compris entre 0 et 255.

Pour créer une image en couleur de 1024 pixels de large par 768 pixels de haut, il faut écrire :

🐍 Script Python
nouvelle_image=Image.new("RGB",(1024,768))

b. Modifier une image⚓︎

Une fois l'image chargée par PIL, il est possible de la modifier en créant les fonctions dont vous avez besoin.

Dans tous les cas suivants, la fonction sera lancée avec fonction( Image.open( fichier( 'ouvrir' ) ), arguments_supplémentaires )

a. Ecrire une fonction rectangle(image,x,y,largeur,hauteur,couleur) qui dessine un rectangle dont le coin supérieur gauche est aux coordonnées [x,y], des dimensions indiquées et de la couleur sous la forme d'un tuple (r,v,b).

Corrigé
🐍 Script Python
def rectangle(image, x, y, largeur, hauteur, couleur):
    for i in range(largeur):
        for j in range(hauteur):
            mon_image.putpixel((x + i, y + j), couleur)
    mon_image.show()
    return mon_image

b. Prendre en compte le fait que les dimensions puissent dépasser les dimensions de l'image. Trouver le moyen de ne pas faire planter le programme dans ce cas.

Corrigé
🐍 Script Python
def rectangle2(image, x, y, largeur, hauteur, couleur):
    for i in range( min(largeur, mon_image.size[0] ) ):
        for j in range( min(hauteur, mon_image.size[1] ) ):
            mon_image.putpixel(( x + i, y + j ), couleur)
    mon_image.show()
    return mon_image

c. Sur le même modèle, écrire une fonction cercle(image,x,y,rayon,couleur)

Corrigé
🐍 Script Python
from math import sqrt
def distance(xa, ya, xb, yb):
    return sqrt((xa - xb) ** 2 + (ya - yb) ** 2 )

def cercle(image, x, y, rayon, couleur):
    for i in range(max(0, x - rayon), min(x + rayon, mon_image.size[0])):
        for j in range(max(0, y - rayon), min(y + rayon ,mon_image.size[1])):
            if distance(i, j, x, y) <= rayon:
                mon_image.putpixel((i, j), couleur)
    mon_image.show()
    return mon_image

d. Ecrire une fonction niveaux_de_gris(image) qui convertit une image en niveaux de gris

Corrigé
🐍 Script Python
def niveaux_de_gris(image):
    nouvelle_image = Image.new('L', image.size)
    for i in range(image.size[0]):
        for j in range(image.size[1]):
            pixel_couleur = image.getpixel((i, j))
            # En faisant une moyenne naïve des couleurs
            pixel_gris = (pixel_couleur[0] + pixel_couleur[1] + pixel_couleur[2]) // 3
            # En prenant en compte le fait que l'oeil est plus sensible au vert, puis au rouge et enfin au bleu
            # il convient de donner un coefficient moins important au bleu
            # 0,2126 × Rouge + 0,7152 × Vert + 0,0722 × Bleu
            # Cpixel_gris = int(0.2126 * pixel_couleur[0] + 0.7152 * pixel_couleur[1] + 0.0722 * pixel_couleur[2])
            nouvelle_image.putpixel((i, j), pixel_gris)
    nouvelle_image.show()
    return nouvelle_image

e. Ecrire une fonction redim(image,facteur) qui redimensionne une image d'un facteur donné.
Ainsi redim(image, 4) pour une image ayant une définition de 1024 x 768 retournerait une image de 1024 / 4 = 256px par 768 / 4 = 192px.

Corrigé
🐍 Script Python
def somme_liste(liste1, liste2):
    sortie = []
    for i in range(len(liste1)):
        sortie.append(liste1[i] + liste2[i])
    return sortie

def divise_entier_liste(liste, k):
    sortie = []
    for i in range(len(liste)):
        sortie.append(int(liste[i] / k))
    return sortie

def redim(image,facteur):
    facteur = int(facteur)
    nouvelles_dimensions = (int(image.size[0] / facteur), int(image.size[1] / facteur))
    nouvelle_image = Image.new('RGB',nouvelles_dimensions)     
    for i in range(nouvelles_dimensions[0]):
        for j in range(nouvelles_dimensions[1]):
            pixel_moyen = [0, 0, 0]
            nombre = 0
            for x in range(facteur):
                for y in range(facteur):
                    pixel_moyen = somme_liste(pixel_moyen, image.getpixel((facteur * i + x, facteur * j + y)))
                    nombre += 1

            pixel_moyen = divise_entier_liste(pixel_moyen, nombre)
            nouvelle_image.putpixel((i, j), tuple(pixel_moyen))
    nouvelle_image.show()
    return nouvelle_image