Dans cette activité, nous allons découvrir les types construits (ou types structurés). Contrairement aux types de bases (int, float, str, bool), les types construits sont des structures de données qui peuvent comporter d'autres types de données.
Chaque type de variable que vous utilisez en python sont des objets sur lesquels vous pouvez agir par le biais :
  • d'opérateurs : +, *, //
  • de fonctions : len, print
  • ou de méthodes : .append(x), .upper()
>>> mot = "bonjour"
>>> mot.upper()
'BONJOUR'
Dans cet exemple, la méthode .upper() agit sur un objet de type str (chaîne de caractères). Le point qui sépare l'objet de la méthode signifie que l'on appelle la méthode de ce type d'objet. Cette méthode s'applique ainsi à l'objet. Il existe de nombreuses méthodes spécifiques aux différents types d'objets.

1. Les séquences

Une séquence est itérable, c'est-à-dire qu'elle offre accès à ses éléments par un indice sous forme d'un nombre entier commençant par 0.
Les listes, p-uplets (ou tuples) et les chaîne de caractères sont des séquences.

Exemple : x = "bonjour" ou x = [4, 6, 2, 7] ou x = (1, 7, 9).

En python :
  • Une chaînes de caractères est encadrée par des doubles guillemets "..." ou des simples guillemets '...'.
  • Une listes est encadrée par des crochets et ses éléments sont séparés par une virgule : [..., ..., ...].
  • Un p-uples (ou tuples) est encadrés par des parenthèses et ses éléments sont séparés par une virgule : (..., ..., ...).
En python, certains types de variables sont immuables. Ils ne peuvent être modifiés.
Un nouvel objet (une nouvelle variable) doit être créé si une de ses valeurs doit être modifiées. C'est le cas des nombres (entiers et flottants), des chaînes de caractères et des p-uplets.

Les listes, au contraire sont muables («mutable» en anglais) et permettent d'ajouter, de retirer, ou de réorganiser leurs éléments sur place au sein de l'objet. Il est alors inutile de définir une nouvelle variable si l'on souhaite apporter une modification.

Opérations communes aux séquences

Dans le tableau suivant, x est une séquence (liste, tuple, chaîne de caractère ...).

x[i]
Accéder au iième élément de x avec l'instruction. Le premier élément porte l'indice 0 et le dernier l'indice len(x)-1.
Si l'indice demandé tombe en dehors de la liste, une erreur est générée : IndexError: list index out of range.
Exemples : [1, 7, 5][0] renvoie l'entier 1, "bonjour"[3] renvoie le caractère "j"
Imbrication : Avec L = ["Hello!", [49, 54], (1, 2, 0)], l'instruction L[1][0] renvoie l'entier 49 .
x[-i]
Accéder à un élément en comptant à partir de la fin.
Exemple : "bonjour"[-1] renvoie le caractère "r".
x[d:f]
Sélectionner une partie («slice» en anglais) des éléments de x. Les éléments sélectionnés seront compris entre d et f exclu. La liste x n'est pas définitivement modifiée (un slice est une copie).
Exemple : (4, 5, 7, 6)[1:3] renvoie le tuple (5, 7).
x[d:f:p]
Sélectionner une partie des éléments de x. Les éléments sélectionnés seront compris entre le dième (début) et fième (fin) exclu avec un pas de p.
Exemple : "bonjour"[4:1:-1] renvoie "ojn" et [4, 5, 7, 6][::-1] renvoie la liste [6, 7, 5, 4].
Quand d et/ou f sont omis, tout est pris depuis le début et/ou jusqu'à la fin.
len(x)
Connaître la longueur, la taille, le nombre d'élément de x.
Exemple : len("Hello!") renvoie l'entier 6 et len([4, 5, 6, 7]) renvoie 4.
max(x) et min(x)
Accéder au minimum, au maximum. Pour des caractères, c'est l'ordre de la table ASCII qui est pris en compte.
Exemple : les instructions : max([5, 7, 1, 6]) renvoie l'entier 7 et min("salut"), le caractère "a".
in et not in
Parcourir les éléments de x ou tester leur présence dans x.
Exemple : "a" in "Hello!" renvoie le booléen False, 4 in [2, 4, 6] renvoie le booléen True.
x.count(n)
Compter le nombre d'apparitions (occurrences) d'un élément n dans x par la méthode x.count(n).
Exemple : [4, 7, 5, 3].count(2) renvoie l'entier 0 car aucun 2 n'est présent dans la liste.
* ou +
Créer rapidement une séquence d'éléments similaires ou concaténer.
Exemple : "a"*3 renvoie la chaîne de caractères "aaa" et [10, 20, 30] + [40, 50] renvoie la liste [10, 20, 30, 40, 50].
x.index(n)
Trouver l'indice de la première occurrence d'un élément dans x.
Exemple : "Hello!".index("l") renvoie l'entier 2.
Que retournent les instructions suivantes :
(1, 7, 5)[5]
L'erreur : IndexError: list index out of range

["Hello!", [49, 54], (1, 2, 0)][0][4]
Le caractère : "o"

[1, 2, 3, 4, 5][-2]
L'entier : 4

"bonjour"[1:4]
La chaîne de caractère : "onj"

"hippopotomonstrosesquippedaliophobie"[4:11:2]
La chaîne de caractère : "oooo"

len([4, 5, 6, 7, 8, 9, 10])
L'entier : 7

max("Salut")
Le caractère : "u"

"o" in "Hello!"
Le booléen : True

"4" in [2, 4, 6]
Le booléen : False car la chaîne de caractère n'est pas dans cette liste qui ne contient que des entier.

"Abracadabra !".count("a")
L'entier : 4

[[0]*3]*2
La liste de liste : [[0, 0, 0], [0, 0, 0]]

"hi"+"po"*2
La chaîne de caractère : "hipopo"

[1, 4, 6, 4].index(4)
L'entier : 1
Palindrome
Écrire une fonction qui renvoie un booléen indiquant si le mot donné en argument est un .
Exemple de palindrome : radar, été, sms, elle, sennes, laval, selles, rotor, ressasser ou encore kayak.
def palindrome(mot):
    for j in range(len(mot)//2): # On balaye la 1re moitié du mot pour la comparer à la 2e
        if mot[j] != mot[-1-j]:  # On teste caractère par caractère
            return False
    return True
def palindrome(mot):
    return mot == mot[::-1]
Pig latin
Le Latin cochon est un mode de communication en argot utilisé en Angleterre par les adultes souhaitant masquer une conversation à un enfant ou à quelqu'un maitrisant mal l'anglais. En France, son équivalent serait un mélange de verlan (inversion des lettres ou des syllabes) et de javanais (rajout d'une syllabe systématique à la fin d'un mot).
Les règles simplifiées du pig latin sont les suivantes :
  • si la 1ère lettre du mot est une voyelle ou un "h", on ajoute aléatoirement "-hay", "-way" ou "-yay" à la fin.
    Exemple : apple → apple-way, apple-hay ou apple-yay, hello → hello-way, hello-hay ou bien hello-yay
  • si la 1ère lettre du mot est une consonne, on la déplace à la fin du mot et on ajoute "ay".
    Exemple : computer → omputer-cay, latin → atin-lay, sister → ister-say
Écrire la fonction pig_latin(mot) donnant la conversion en pig latin d'un mot.
from random import choice

def piglatin(mot):
    if mot[0] in "aeéèêiïîoöôuüûyh":
        return mot + choice(["-hay", "-way", "-yay"])
    else:
        return mot[1:] + mot[0] + "ay"

Les chaînes de caractères

Les chaînes de caractères, présentée comme un type de base dans le chapitre précédent, sont en réalité un type construit. Ce sont des séquences immuables. En plus des opérations applicables à toutes les séquences, en voici d'autres spécifiques aux chaînes de caractères :

Dans le tableau suivant, x est une chaîne de caractère.

x = "" ou bien
x = ''
Créer une chaîne de caractère vide.
Remarque : la chaîne de cractère vide est la seule ayant une valeur booléenne False.
x.upper() et x.lower()
Mettre l'ensemble d'une chaîne de caractères en majuscule ou en minuscule.
Exemple : "hello".upper() renvoie la chaîne de caractères "HELLO".
x.capitalize()
Mettre uniquement la première lettre en majuscule.
Exemple : "bonjour".capitalize() renvoie la chaîne de caractères "Bonjour".
x.replace(a,b)
Remplacer toutes les occurrences d'un caractère par un autre.
Exemple : "forte".replace("t", "m") renvoie la chaîne de caractères "forme".
x.find(y)
Donne l'indice de position de la première occurence de la chaîne de caractère y dans x.
Exemple : "Si six scies scient six cyprès, six cent six scies scient six cent six cyprès.".find("six") renvoie l'entier 3.
list(x)
Transformer une chaîne de caractères en une liste de ses caractères
Exemple : list("jour") renvoie la liste ["j", "o", "u", "r"]
x.split()
Découper une chaîne de caractères par ses espaces (ou tout autre caractère séparateur donné en argument de la fonction).
Exemple : "Baptiste MARTIN".split() renvoie la liste ["Baptiste", "MARTIN"]
Il est possible d'affecter toutes les parties à plusieurs variables par une affectation multiple :
Exemple : prenom, nom = "Baptiste MARTIN".split()
ord(x)
Accéder à la valeur décimale d'un caractère dans la table ASCII.
À l'inverse, on peut accéder à un caractère à partir de son code décimal avec la fonction chr().
Exemple : ord("a") renvoie l'entier 97 et ord("A") l'entier 65 ; aussi, chr(65) renvoie "A".
x.strip()
Retire tous les espaces (ou tout autre caractère donné en argument de la fonction) du début et de la fin de la chaîne de caractère. Exemple : " Turing ".strip() renvoie la chaîne de caractères "Turing"
x.format()
Formater une chaîne de caractère :
Exemple :
Avec des indices : "Bonjour {0} de la planète {1}.".format("Julie", "Terre") renvoie la chaîne de caractères "Bonjour Julie de la planète Terre."
Avec des clés : "Bonjour {nom} du lycée {lyc}.".format(nom="Victor", lyc="Déodat") renvoie la chaîne de caractères "Bonjour Victor du lycée Déodat."
f"Bonjour {x}"
Formater une chaîne de caractère de façon bien plus lisible (on parle de «f-string»).
Exemple : Si a = 2 et b = 3 alors f"{a} + {b} = {a+b}" renvoie la chaîne de caractère avec "2 + 3 = 5". Ce qui est entre accolades est interprété comme une instruction python.
\
Caractère d'échappement : antislash. Il permet d'éviter l'interprétation d'un caractère dans une chaîne de caractère.
Exemple : "Il s'écria : \"Je m'appelle O'neill avec deux \"L\".\"" retourne la chaîne de caractères Il s'écria : "Je m'appelle O'neill avec deux "L"." Ici on évite que le premier guillemet soit interprété comme étant la fin de la chaîne de caractère en l'échappant avec \.
Que retournent les instructions suivantes :
"Mathis".lower()
La chaîne de caractère : "mathis"

"MATHIS".capitalize()
La chaîne de caractère : "Mathis"

"sceau".replace("c", "").replace("eau", "ot").replace("o", "au")
La chaîne de caractère : "saut"

"P_3_3".split("_")
La liste : ["P", "3", "3"]

"sssserpents".strip("s")
La chaîne de caractère : "erpent"

f"Bonjour {nom} !" sachant que nom = "Raphaël"
La chaîne de caractère : "Bonjour Raphaël !"
Rechercher
Rechercher dans la documentation python comment utiliser la méthode .find() pour obtenir la position du deuxième "six" dans "Si six scies scient six cyprès, six cent six scies scient six cent six cyprès.".find("six").
Il est très important que vous sachiez trouver des informations dans la documentation python pour devenir un programmeur autonome et efficace.
Après une simple recherche, on trouve le plan de cette méthode : str.find(sub[, start[, end]])
Ce plan montre qu'il y a deux paramètres facultatifs (entre crochets) : start et end qui permette d'encadrer la zone de recherche.
On apprend aussi que dans le cas où aucune occurrence n'est trouvée, cette méthode retourne l'entier -1.
s = "Si six scies scient six cyprès, six cent six scies scient six cent six cyprès."
i = s.find("six", s.find("six")+1)
The name game
Shirley Ellis était une chanteuse afro-américaine des années 70, connue pour son titre « The name game » vendu à plus d'un million d'exemplaires et largement utilisé dans certains films publicitaires. Le principe du refrain était de prendre le prénom d'une personne du public et de le faire varier selon certaines règles.
Cas n° 1 : Si la première lettre est une voyelle, on ne modifie pas celle-ci mais on se contente de rajouter le « b », le « f » ou le « m ».
Eric, Eric, bo-beric
Banana-fana fo-feric
Fee-fi-mo-meric
Eric !
1 - Coder la fonction cas1(mot) en pyton générant le refrain de « The name game » pour le cas n°1. Attention aux majuscules !

Remarque : Le caractère « saut de ligne » dans une chaîne de caractère est \n. def cas1(nom): refrain = nom+', '+nom+', bo-b'+nom.lower()+"\n"+\ "Banana-fana fo-f"+nom.lower()+"\n"+\ "Fee-fi-mo-m"+nom.lower()+"\n"+\ nom+" !" return refrain
Cas n° 2 :Si la 1ère lettre est un « b », un « f » ou un « m », celle-ci est simplement supprimée afin que le son ne soit pas répété.
Billy, Billy, bo-illy
Banana-fana fo-filly
Fee-fi-mo-milly
Billy !
Fred, Fred, bo-bred
Banana-fana fo-red
Fee-fi-mo-mred
Fred !
2 - Coder la fonction cas2(mot) en pyton générant le refrain de « The name game » pour le cas n°2.
def cas2(nom):
    if nom[0] == "B": nb = nom[1:]
    else: nb = "b"+nom[1:]
    if nom[0] == "F": nf = nom[1:]
    else: nf = "f"+nom[1:]
    if nom[0] == "M": nm = nom[1:]
    else: nm = "m"+nom[1:]
    refrain = nom+', '+nom+', bo-'+nb+"\n"+\
              "Banan-fana fo-"+nf+"\n"+\
              "Fee-fi-mo-"+nm+"\n"+\
              nom+" !"
    return refrain
Cas n° 3 :Dans tous les autres cas, la première lettre est remplacé par « b », « f » ou « m ».
Paul, Paul, bo-baul
Banana-fana  fo-faul
Fee-fi-mo-maul
Paul !
Katie, Katie, bo-batie
Banana-fana  fo-fatie
Fee-fi-mo-matie
Katie !
3 - Coder la fonction cas3(mot) en pyton générant le refrain de « The name game » pour le cas n°3.
def cas3(nom):
    refrain = nom+', '+nom+', bo-b'+nom[1:]+"\n"+\
              "Banana-fana fo-f"+nom[1:]+"\n"+\
              "Fee-fi-mo-m"+nom[1:]+"\n"+\
              nom+" !"
    return refrain

4 - Coder la fonction principale the_name_game(mot) appelant une des trois fonctions précédentes selon le cas.
def the_name_game(nom):
    if nom[0] in "aeéèêiïîoöôuüûyh":
        return cas1(nom.capitalize())
    elif nom[0] in "bfm":
        return cas2(nom.capitalize())
    else:
        return cas3(nom.capitalize())

Les listes

Attention : Les méthodes vues ici modifient directement la liste d'origine car les listes sont muables. Cela peut être source d'erreur comme dans cet exercice :
Attention aux erreurs !
Prédire ce qu'affiche le code suivant :
a = [1, 2, 3]
b = a
b[0] = 5
print(a)
Il affiche : [5, 2, 3]
On pourrait croire qu'à la ligne 2, on effectue une sauvegarde de la liste a dans la variable b mais il n'en est rien. La variable b n'est qu'un nouveau pointeur vers la même liste vers laquelle pointait déjà a.
Comment résoudre ce problème et réaliser une vraie copie ?
Avec l'instruction b = a[:], on réalise la copie du début à la toute fin de la liste a dans la variable b.
En plus des opérations applicables à toutes les séquences, en voici d'autres spécifiques aux listes :

Opérations sur les listes

Dans le tableau suivant, x est une liste.

x = []
Créer une liste vide.
x.append(e)
Rajouter un élément en fin de liste. Équivalent à x = x + [5] ou x += [5] mais qui sont moins performants en terme de ressources mémoire car une copie entière de la liste est réalisée.
Exemple : Si liste = [1, 2, 3, 4], liste.append(5) ne retourne rien mais modifie directement l'objet liste car les liste sont muables.
x.insert(i, e)
Insérer l'élément e en position d'indice i dans une liste.
x.extend(li)
Concaténer une liste à une autre. Équivalent à x = x + [5, 6, 7] ou x += [5, 6, 7]
Exemple : liste = [2, 4, 8, 10] puis liste.extend(2, 6)
x.sort()
Trier (tri rapide) la liste par ordre croissant.
Exemple : liste = [5, 4, 9, 2] puis liste.sort() ; liste vaut alors [2, 4, 5, 9].
x.reverse()
Modifie la liste en renversant l'ordre de ses éléments.
N'est pas équivalent à liste[::-1] qui renvoie, lui, une copie de la liste retournée.
x.remove(e)
Enlever la première occurrence d'une valeur dans une liste.
Exemple : Si liste = [2, 3, 4, 3, 6, 8], liste.remove(3) modifie la liste en [2, 4, 3, 6, 8].
a = x.pop(i)
Extraire la valeur en position d'indice i dans la liste et l'affecter à une variable.
Exemple : Si liste = [2, 3, 4, 12, 6, 8], liste.pop(3) retourne l'entier 12 et modifie la liste.
del liste[i]
Effacer la valeur en position d'indice i dans une liste.
Exemple : Si liste = [4, 5, 3, 2, 7], del liste[2] retire l'entier 3 de la liste.
del liste supprime complètement la liste.
Que devient la liste liste = [1, 2, 3, 4] après chacune des instructions suivantes (on considère pour chaque question, l'état de la liste modifiée par les questions précédentes puisque qu'une liste est muable) :
liste.append(5).extend(2, 6)
Une erreur : AttributeError: 'NoneType' object has no attribute 'insert' car la première partie liste.append(5) ne retournant rien, il est impossible d'appliquer la méthode .extend(2, 6) sur rien.

liste.append(3)
Valeur de la variable 'liste' : [1, 2, 3, 4, 5, 3]. Attention le .append(5) s'est bien appliquée. l'erreur n'est survenue qu'après que l'objet ait été modifié.

liste.insert(2, 5)
Valeur de la variable 'liste' : [1, 2, 5, 3, 4, 5, 3]

liste.sort()
Valeur de la variable 'liste' : [1, 2, 3, 3, 4, 5, 5]

liste.pop(2)
Valeur de la variable 'liste' : [1, 2, 3, 4, 5, 5]

liste.remove(5)
Valeur de la variable 'liste' : [1, 2, 3, 4, 5]

liste.reverse()
Valeur de la variable 'liste' : [5, 4, 3, 2, 1]
Trier
1 - Rechercher dans la documentation python comment utiliser la méthode .sort() pour trier les éléments du plus grand au plus petit.
Il est important que vous sachiez trouver des informations dans la documentation python pour devenir un programmeur autonome et efficace.
Après une simple recherche, on trouve le plan de cette méthode : sort(*, key=None, reverse=False)
Ce plan montre qu'il y a deux paramètres définis par des clés avec des valeurs par défaut : key=None et reverse=False.
Le premier donne la possibilité de définir une fonction de tri particulière. Nous verrons cela dans la chapitre sur le traitement des données en table.
Le deuxième permet de choisir l'ordre du tri. Avec l'instruction liste.sort(reverse=True) les valeurs seront triées de la plus grande à la plus petite.

2 - Que va faire la méthode .sort() sur la liste ["cochon", "cheval", "chien", "chat"] ?
D'après la documentation de la méthode .sort(), celle-ci utilise l'opérateur > pour classer les éléments de la liste. Or cet opérateur appliqué à des chaînes de caractères, compare le code ASCII des caractères. En résumé, la liste de mot sera triée par ordre alphabétique et on obtiendra : ["chat", "cheval", "chien", "cochon"].
Sélectionner/Éliminer
Écrire une fonction sup5c(liste) qui à partir d'une liste de mots, renvoi la liste purgée de tous les mots ayant exactement 5 caractères.
Exemple de liste : animaux = ['lapin', 'chat', 'chien', 'poisson', 'vache', 'cochon', 'oiseau']
def sup5c(liste):  # ATTENTION ! Mauvaise solution !
    for e in liste:
        if len(e) == 5:
            liste2.remove(e)
    return liste2
Attention : Cette solution est dangereuse car elle paraît acceptable mais génère des bugs. En effet, la liste qui est parcourue et modifiée pendant le parcours ce qui peut conduire à ignorer des éléments de la liste. Vérifier qu'elle ne fonctionne pas avec la liste animaux = ['lapin', 'chien', 'vache', 'cochon', 'oiseau'].
Solution 1 : Créer une copie de la liste pour y supprimer les éléments :
def sup5c(liste):
    liste2 = liste[:]  # Copie de la liste
    for e in liste:
        if len(e) == 5:
            liste2.remove(e)
    return liste2
Solution 2 :Créer une liste vide pour y insérer les éléments retenus :
def sup5c(liste):
    liste2 = []  # Liste vide
    for e in liste:
        if len(e) != 5:
            liste2.append(e)
    return liste2

Construire une liste par compréhension

[i for i in range(10)] génère une liste d'entier de 0 à 9. Cette instruction est équivalent à list(range(10)).
Exemple : a = [i*2 for i in range(5)]

Générer par compréhension
Donner l'instruction permettant de générer les listes suivantes par compréhension :
[0, 1, 4, 9, 16, 25]
[x**2 for x in range(6)]

[1, 2, 5, 10, 17, 26]
[x**2 + 1 for x in range(6)]

La liste animaux de l'exercice précédent en mettant en majuscule la première lettre de chaque nom.
[x.capitalize() for x in animaux]

Les p-uplets (ou tuples)

Les tuples sont des séquences immuables. Il n'est pas possible de modifier, d'ajouter ou d'enlever un élément sans devoir recréer un autre tuple, contrairement aux listes. C'est utile et sécurisant pour des données dont la structure ne doit pas changer comme pour des coordonnées par exemple.
Un tuple avec deux élément est appelé une paire, avec trois éléments, un triplet, etc.
coord = (4, 2)  	# affectation du tuple (4, 2) à la variable coord

Affectation multiple

Ils sont souvent utilisés sans s'en rendre compte car les parenthèses qui les encadrent sont omises. C'est le cas quand on réalise une affectation multiples ou un échange de valeurs.
# affectation multiple :
a, b = 2, 3  		# a prend la valeur 2 et b la valeur 3
# échange de valeurs
b, a = a, b 		# a prend la valeur de b et b celle de a

Utilisation d'un tuple avec les fonctions

Pour les arguments : Pour que le contenu du tuple arg = (10, 3) soit correctement distribué sur les paramètres a et b de la fonction div_eucl, il faut faire précéder *arg d'un astérisque dans l'appel de la fonction.

Pour le retour : Si une fonction a besoin de retourner plusieurs valeurs, il est possible de retourner un tuple. Dans ce cas, les parenthèses doivent/peuvent être omises. Il est alors possible d'utiliser plusieurs variables pour recevoir séparément les valeurs retournées par la fonction grâce à une affectation multiple, ou bien une seule variable qui sera alors un tuple.

def div_euclidienne(a, b):   # définition d'une fonction qui prend deux arguments
    return a//b, a%b         # et renvoi un tuple de deux valeurs (parenthèses omises)

arg = (10, 3)                # définition des arguments à donner à la fonction
x, y = div_euclidienne(*arg) # Affectation multiple du retour de la fonction
res = div_euclidienne(*arg)  # Affectation simple ()

print(x, type(x))
print(y, type(y))
print(res, type(res))
Tester le code ci-dessus.
Analyse fréquentielle
Vous devez définir une fonction qui compte le nombre de fois qu'apparaît chaque chiffre dans un nombre. La fonction doit prendre en argument une chaîne de caractère fait de chiffres (ex : "661163")
et retourner une liste de tuples contenant chacun un chiffre et son nombre d'occurrences dans le nombre (ex : [(6, 3), (1, 2), (3, 1)]).
def compte(num):
    num = str(num)  # On converti en str afin de pouvoir parcourir chaque chiffre du nombre
    liste = []
    cars = ""
    for c in num:
        if c not in cars:
            n = 0
            cars += c
            for c2 in num:
                if c == c2:
                    n +=1
            liste.append((int(c),n))
    return liste

Les tableaux

En python, les tableaux n'existent pas en tant que type de variable. Pour créer un tableau, il faut utiliser une structure de données de type : liste de listes. Chaque ligne d'un tableau est une liste contenant autant d'élément que de colonnes dans le tableau.

# Création d'un tableau de 3 lignes et de 4 colonnes
# avec une liste de 3 listes contenant chacune 4 éléments
tab = [[0, 1, 1, 0],      # 1re ligne
       [1, 2, 2, 1],      # 2e ligne
       [3, 5, 5, 3]]      # 3e ligne
Remarque : L'indentation des lignes 4 et 5 n'est pas obligatoire mais fait partie des règles PEP8 permettant une meilleure lisibilité de la structure de donnée.

Accéder à un élément

Il faut d'abord donner l'indice de la ligne pour sélectionner la liste correspondante puis l'indice de la colonne.
Attention les indices commencent à 0 et l'origine d'un tableau est situé en haut à gauche.
a = tab[0][1]   # renvoi l'élément de la 1ère ligne et de la deuxième colonne
Plateau du Scrabble
Définir un tableau de 15x15, représentant le plateau du jeu du Scrabble.
Case du plateau de jeuValeur
Simple (verte)1
Lettre Double (bleu clair - LD)2
Lettre Triple (bleu foncé - LT)3
Mot Double (jaune - MD)4
Mot Triple (rouge - MT)5
plateau = [[1]*15 for i in range(15)]

lettre_double = [(0,3), (0,11), (2,6), (2,8), (3,0), (3,7), (3,14), (6,2), (6,6), (6,8),
                 (6,12),(7,3), (7,11), (8,2), (8,6), (8,8), (8,12), (11,0), (11,7),
                 (11,14), (12,6), (12,8), (14,3), (14,11)]
lettre_triple = [(1,5), (1,9), (5,1), (5,5), (5,9), (5,13), (9,1), (9,5), (9,9), (9,13),
                 (13,5), (13,9)]
mot_double = [(1,1), (2,2), (3,3), (4,4), (10,10), (11,11), (12,12), (13,13), (1,13),
              (2,12), (3,11), (4,10), (10,4), (11,3), (12,2), (13,1)]
mot_triple = [(0,0), (0,7), (0,14), (7,0), (7,14), (14,0), (14,7), (14,14)]

for c in lettre_double:
    plateau[c[0]][c[1]] = 2
for c in lettre_triple:
    plateau[c[0]][c[1]] = 3
for c in mot_double:
    plateau[c[0]][c[1]] = 4
for c in mot_triple:
    plateau[c[0]][c[1]] = 5

for i in plateau: print(i)

Créer un tableau par compréhension

L'instruction [[i]*3 for i in range(2)] génère le tableau :
[[0, 0, 0],
 [1, 1, 1]]
En effet, si on regarde la structure de cette instruction, les crochets extérieurs forme une liste à l'intérieur de laquelle il est littéralement écrit que l'on y met [i]*3 c'est-à-dire [i, i, i] pour chaque i dans range(2) c'est-à-dire [0, 1].
Créer le tableau suivant par compréhension :
[[0, 1, 2, 3, 4],
 [1, 2, 3, 4, 5],
 [2, 3, 4, 5, 6],
 [3, 4, 5, 6, 7],
 [4, 5, 6, 7, 8]]
[[i+j for i in range(5)] for j in range(5)]

Parcourir un tableau

Parcourir un tableau signifie passer par toutes ses cases. Cela est possible en imbriquant deux boucle for.
# Pour parcourir les valeurs
for ligne in tab:                  # parcourt les lignes du tableau, une à une
    for el in ligne:               # parcourt les éléments de la ligne, un par un

# Pour parcourir les valeurs avec leurs coordonnées
for y in range(len(tab)):          # y est l'indice de la ligne (en partant d'en haut)
    for x in range(len(tab[y])):   # x est l'indice de la colonne (en partant de la gauche)
        el = tab[y][x]             # el prend la valeur de la y-ième ligne et x-ième colonne
Tableau aléatoire et recherche
1 - Définir la fonction tableau_aleatoire(x, y) qui génère un tableau d'entiers aléatoires compris entre 0 et 1000 avec x lignes et y colonnes.
Consulter la documentation de la fonction randint.
from random import randint

def tableau_aleatoire(x, y):
    return [[randint(0, 1000) for i in range(y)] for j in range(x)]

2 - Définir une fonction qui retourne la valeur maximale d'un tableau d'entier donné en argument (vous pouvez utiliser la fonction précédente pour générer ce tableau d'entiers).
def maximum(tab):
    m = tab[0][0]                     # On prend la toute première valeur du tableau
    for y in range(len(tab)):         # Balaye toutes les lignes
        for x in range(len(tab[y])):  # Balaye toutes les colonnes
            if tab[y][x] > m:         # Si la valeur est plus grand que m
                m = tab[y][x]         # Remplacer la valeur dans m
    return m
Remarques : Attention à ne pas utiliser max comme nom de variable car il s'agit d'une fonction déjà définie en python.

Les dictionnaires

Les dictionnaires sont des objets structurés pouvant contenir d'autres objets tous référencés par une clé. À la différence des listes, des p-uplets (tuples) ou des chaînes de caractères qui sont des séquences : liste finie et ordonnée d'objets repérés par un indice (0, 1, 2 … ), dans un dictionnaire, les objets sont repérés par des clés.
Un dictionnaire est défini par des accolades { ... : ..., ... : ..., }, la clé est séparée de sa valeur par deux points et les couples clé:valeur par des virgules. Une clé peut être une chaine de caractère, un entier, un flottant ou un booléen tandis qu'une valeur peut être de tout type.

Créer un dictionnaire

dico = {}                                 # crée un dictionnaire vide
dico = {"nom":"O'neill", "taille":1.76}   # crée un dictionnaire avec deux éléments :
                                          # une chaîne de caractère "O'neill" repéré par la clé "nom"
                                          # et un flottant 1.76 repéré par la clé "taille".
dico["prenom"] = "Jack"                   # ajoute la chaîne de caractère "Jack" avec la clé "prenom"

Obtenir la taille d'un dictionnaire (nombre d'éléments)

Même si un dictionnaire n'est pas une séquence itérable, on peut utiliser la fonction len() pour en connaître la taille.
len(dico)			# renvoie le nombre d'élément dans le dictionnaire dico

Supprimer des éléments d'un dictionnaire

del dico["prenom"]        # supprime l'élément de la clé "prenom" du dictionnaire dico
b = dico.pop("taille")    # supprime l'élément de la clé "taille" du dictionnaire et affecte sa valeur à la variable b
defis = {"P_3_1":{"nb_points":1, "titre":"De Fahrenheit à Celsuis", "themes":["python", "variables"]},
         "P_3_2":{"nb_points":1, "titre":"De pouce à cm", "themes":["python", "variables"]},
         "P_3_3":{"nb_points":2, "titre":"Étoile rouge", "themes":["python", "test"]},
         "P_3_4":{"nb_points":3, "titre":"Cube coloré en perspective", "themes":["python", "boucle"]}
        }
1 - Quelle instruction permet d'obtenir le titre du défis "P_3_2" ?
defis["P_3_2"]["titre"]

2 - Quelle instruction permet d'ajouter le thème "FOR" au défi "P_3_4" ?
defis["P_3_4"]["themes"].append("FOR")

3 - Quelle instruction modifie le nombre de points du défi "P_3_3", en le passant de 2 points à 4 points ?
defis["P_3_3"]["nb_points"] = 4

Accéder aux éléments d'un dictionnaire

dico = {"taille":1.73, "masse":70}
dico["taille"]      # récupère la valeur de la clé "taille" du dictionnaire
dico.keys()         # renvoie une séquence avec les clés du dictionnaire : ["taille", "masse"]
dico.values()       # renvoie une séquence avec les valeurs du dictionnaire : [1.73, 70]
dico.items()        # renvoi une séquence de tuple (clé, valeur) : [("taille", 1.73), ("masse", 70)]
for cle, val in dico.items(): # boucle sur les clés et les valeurs
for val in dico.values():     # boucle sur les valeurs
for cle in dico:              # boucle sur les clés (équivalent à for cle in dico.keys():)
if "prenom" in dico	:         # vérifie la présence de la clé "prenom" dans le dictionnaire : False
if not "prenom" in dico	:     # vérifie l'absence de la clé "prenom" dans le dictionnaire : True
Remarque : Pour trouver l'élément il faut parcourir tout le dictionnaire. Le temps de parcours est proportionnel à la taille du dictionnaire. Le coût en temps est linéaire.
Score au Scrabble
Le Scrabble est un jeu ou il faut former des mots. Le score obtenu par le joueur est la somme des points associés à chaque lettre du mot formé. Les points associés à chaque lettre dans la version française sont fournis dans ce dictionnaire :
scrabble = {'A':1, 'B':3, 'C':3, 'D':2, 'E':1, 'F':4, 'G':2, 'H':4, 'I':1,
            'J':8, 'K':10, 'L':1, 'M':2, 'N':1, 'O':1, 'P':3, 'Q':8, 'R':1,
            'S':1, 'T':1, 'U':1, 'V':4, 'W':10, 'X':10, 'Y':10, 'Z':10}
Créer la fonction score(mot) qui à partir du mot formé, retourne le score. (Ne pas tenir compte du plateau de jeu pour cet exercice !)
def score(mot):
    scrabble = {'A':1, 'B':3, 'C':3, 'D':2, 'E':1, 'F':4, 'G':2, 'H':4, 'I':1,'J':8, 'K':10, 'L':1, 'M':2, 'N':1, 'O':1, 'P':3,
            'Q':8, 'R':1,'S':1, 'T':1, 'U':1, 'V':4, 'W':10, 'X':10, 'Y':10, 'Z':10}
    rep = 0
    for car in mot.upper():
        rep += scrabble[car]
    return rep

Dictionnaire de fonctions

def ma_fonction() :             # définition d'une fonction appelée ma_fonction
       print("Hello world!")    # qui écrit "Hello world!" dans la console

dico = {"saluer":ma_fonction}   # creation d'un dictionnaire contenant la fonction
dico["saluer"]()                # appel de la fonction ma_fonction
Remarque : Dans la création du dictionnaire, la fonction n'est pas appelée car il n'y a pas les parenthèses. Elle est appelée à la ligne suivante grâce aux parenthèses qui pourrait accueillir des arguments si nécessaire.

Convertir une liste de tuples en dictionnaire et inversement

liste = [("a",1), ("b",2)]    # définition d'une liste de tuples (clé, valeur)
dict(liste)                   # conversion en dictionnaire

dico = {"a":1, "b":2}         # EN SENS INVERSE : définition d'un dictionnaire
list(dico.items())            # conversion en liste de tuples (clé, valeur)

Utilisation d'un dictionnaire pour passer des arguments à une fonction

def div_eucl(a, b):     # définition d'une fonction qui prend deux arguments
    return a//b, a%b    # et renvoi un tuple de deux valeurs

arg = {"b":3, "a":10}   # définition des arguments nommés à donner à la fonction
div_eucl(**arg)         # appel de la fonction avec les arguments nommés du dictionnaire
Pour que le contenu du dictionnaire arg soit bien distribué aux bons paramètres a et b de la fonction div_eucl, il faut que les clés du dictionnaire aient le même nom que les paramètres de la fonction et le faire précéder de deux astérisques **arg dans l'appel de la fonction.

Variables, alias, valeurs et références

Lorsqu'une valeur d'un type construit est affecté à une variable, en réalité, ce qui est réellement affecté à cette variable, c'est la référence dans la mémoire (identifiant unique) de cette valeur.
Il faut alors bien faire attention aux objets muables pour éviter beaucoup d'erreur.
En effet si on affecte une liste (objet muable) à la variable a (ligne 1), puis que l'on affecte la variable a à une nouvelle variable b (ligne 2), on ne crée pas de copie de la valeur mais une copie de la référence de la valeur. b est alors un alias de a. Ainsi a et b ont la même référence, c'est-à-dire qu'ils pointent vers le même objet.
L'erreur classique est alors de croire que l'on a fait une copie de sauvegarde, alors qu'en réalité on modifie aussi l'objet initial et que l'on peut modifier l'un sans modifier l'autre.
Pour savoir si deux variables sont des alias, il y a la possibilité d'obtenir leur référence avec la fonction id(). Il existe aussi le mot-clé is qui vérifie si deux variables sont en réalité le même objet.
a = [1, 2, 3]
b = a

print(id(a))
print(id(b))
print(a is b)

a[0] = 5
print(b[0])
Commenter chaque ligne du code précédent.
a = [1, 2, 3]     # Création d'un objet liste. Sa référence (identifiant) est stockée dans a
b = a             # Création d'un alias pointant vers le même objet liste

print(id(a))      # a et b ont la même référence (identifiant)
print(id(b))
print(a is b)     # ils s'agit du même objet

a[0] = 5          # si on modifie une valeur dans la liste en utilisant l'alias a,
print(b[0])       # puisque c'est le même objet, elle est aussi modifiée en passant par l'alias b
Si l'on souhaite créer une réelle copie d'un type construit, c'est-à-dire, par exemple une deuxième liste identique à la première, il est possible d'utiliser l'une des instructions suivantes :
b = a.copy()
b = a[::]
Attention, ces deux techniques sont insuffisantes en cas d'imbrication de types construits. Seul le premier niveau est réellement copié.
a = [[1, 2], 3]
b = a.copy()
a[1] = 100
a[0][0] = 200
print(b)          # affiche [[200, 2], 3]
Pour créer une copie intégrale, quelque soit la profondeur, il y a la possibilité d'utiliser la fonction deepcopy() du module copy.
from copy import deepcopy

a = [[1, 2], 3]
b = deepcopy(a)
a[1] = 100
a[0][0] = 200
print(b)          # affiche [[1, 2], 3]
Zen du Python
Après ces deux chapitres sur python, vous êtes un Apprenti Python digne de recevoir le Zen du Python (PEP 20) !
Pour cela, exécuter l'instruction import this dans une console python.
  1. Préfèrer le beau au laid,
  2. l'explicite à l'implicite
  3. le simple au complexe,
  4. le complexe au compliqué,
  5. le déroulé à l'imbriqué,
  6. l'aéré au compact.
  7. La lisibilité compte.
  8. Les cas particuliers ne le sont jamais assez pour violer les règles,
  9. … même s'il faut privilégier la praticité à la pureté.
  10. Ne jamais passer les erreurs sous silence,
  11. … ou les faire taire explicitement.
  12. En cas d'ambiguïté, résister à la tentation de deviner.
  13. Il devrait y avoir une, et de préférence une seule, façon évidente de procéder,
  14. … même si cette façon n'est pas évidente à première vue, à moins d'être Hollandais.
  15. Mieux vaut maintenant que jamais,
  16. … même si jamais est souvent préférable à immédiatement.
  17. Si l'implémentation s'explique difficilement, c'est une mauvaise idée.
  18. Si l'implémentation s'explique facilement, c'est peut-être une bonne idée.
  19. Les espaces de noms sont une sacrée bonne idée, utilisons-les plus souvent !