Introduction à la Programmation Python


Le langage [1/3]

  • Variables
  • Types de données
  • Fichiers

Formation permanente du CNRS, Délégation Alsace

Février - Mars 2017


Auteurs :

Contenu sous licence CC BY-SA 4.0

Langage python et sa syntaxe

Variables

Pour accéder aux données, on leur donne des noms que l'on appelle des variables.

Pour donner un nom à une donnée, on utilise l'opérateur d'assignation '='.

Exécutez la cellule suivante (SHIFT+ENTER) pour définir trois variables nommées : age, prénom et taille.

In [ ]:
# Par exemple: donnons la valeur 23 à la variable 'age'
age = 23
# Les variables peuvent se référer à divers types de données: des chaînes de caractères...
prenom = 'Julien'
# Des nombres réels, etc...
taille = 1.83

Pour se servir de la donnée référencée par une variable, il suffit d'utiliser le nom cette variable.

La fonction print() affiche à l'écran ce qui lui est passé en paramètre. On peut lui donner plusieurs paramètres séparés par des virgules et print les affichera tous, séparés par un espace.

In [ ]:
print('Julien', 23, 1.83)
print(prenom, 'a', age, 'ans, et mesure', taille, 'mètre')

Les variables peuvent changer et ainsi se référer à une autre donnée.

In [ ]:
age = 23
print(age)
age = 24
print(age)

Les variables n'ont pas de type propre: c'est la donnée qui est typée, pas la variable qui la référence.
Elles peuvent donc faire référence à une donnée d'un autre type après une nouvelle assignation.

La fonction type() retourne le type effectif de la donnée passée en paramètre.

In [ ]:
# Des nombres
age = 23
print(type(age))
# Les variables peuvent aussi changer de type : chaîne de caractères
age = 'vingt quatre ans'
print(type(age))
# Sans limites...
age = 24.5
print(type(age))
# Attention aux pièges...
age = '25'
print(type(age))

Une variable peut être initialisée avec des valeur constantes, comme vu précédement, mais aussi à partir d'autres variables ou des valeurs de retour de fonctions, etc...

La fonction max() retourne le plus grand de ses paramètres.

In [ ]:
a = 1
b = a
c = a * 2
d = max(a, 2, 3, c)
print(a, b, c, d)

Deux variables peuvent référencer le même objet, les modifications faites par l'intermédiaire d'une des variables sont visibles par toutes les autres.

In [ ]:
a = []
b = a
print(a, b)
a.append(1)
print(a, b)

Les variables, une fois définies dans une cellule exécutée, continuent d'exister dans les suivantes.

Note

En cas de redémarrage du notebook, toutes les variables existantes sont détruites, il faut donc ré-exécuter les cellules qui les définissent si l'on veut de nouveau pouvoir les utiliser.

In [ ]:
abcd = 1234

Ici, la variable nommée 'abcd' survit, d'une cellule à la suivante...

In [ ]:
print(abcd)

Si on veut faire disparaître une variable, on peut utiliser le mot clé interne del.

In [ ]:
# Cette cellule génère une erreur
a = 2
print(a)
del(a)
print(a)

Note : del est aussi utilisé pour enlever des éléments dans des conteneurs modifiables (listes, dictionnaires). Nous aborderons ce sujet plus tard.

Types de données

Types de base

  • None
  • Booléens
  • Numériques
    • entiers
    • flottants
    • complexes

Séquences

  • Chaines de caractères
  • listes
  • tuples

Conteneurs

  • Dictionnaires
  • Ensembles

Fichiers

Types de base

None

  • Il existe dans python un type de données particulier : None.
  • None représente un objet sans valeur. On s'en sert comme valeur de retour en cas d'erreur ou pour représenter un cas particulier.
  • None est équivalent à NULL en java, C.
In [ ]:
a = None
print(a)
print(type(a))

Booléens

Les booléens ne peuvent avoir que deux valeurs :

True, False

On peut utiliser la fonction bool() pour construire un booléen.

Dans un contexte booléen, toutes ces valeurs sont équivalentes à False :

  • None
  • le zero des types numériques, par exemple : 0, 0.0, 0j.
  • les séquences vides, par exemple : '', (), [].
  • les dictionnaires vides, par exemple, {}.

Tout le reste est équivalent a True :

  • une valeur numérique différente de zéro : 2, 3.14, 0.5j
  • une séquence non vide : 'abc', (1, 0.5, 'toto'), [None]
  • un dictionnaire non vide : {'ane': True, 'chat': True}

Quelques exemples de constructions de valeurs booléennes à partir d'autres types

In [ ]:
print(bool(None), bool())
print(bool(0), bool(1))
print(bool(0.0), bool(0.5))
print(bool(0j), bool(3j))
print(bool(''), bool('abc'))
print(bool(()), bool((1, 0.5, 'toto')))
print(bool([]), bool([None]))
print(bool({}), bool({'ane': True, 'chat': True}))

Exemple d'utilisation d'un contexte booléen

In [ ]:
Am_I_OK = True
if Am_I_OK:
    print('OK')
else:
    print('KO')
print(Am_I_OK)
print(type(Am_I_OK))

Exercice :

  1. Supposons que vous soyez malade, mettez Am_I_OK à la valeur False puis réexecutez la cellule.
  2. Essayez avec d'autres types : listes, None, nombres, etc...

Numériques

entiers (précision illimitée)

In [ ]:
# Il n'y a plus de distinction entre les entiers "courts" et les entiers "longs"
entier = 4
print(entier)
print(type(entier))
# Ce nombre nécéssite 131 bits
entier = 1415926535897932384626433832795028841971
print(entier)
print(type(entier))

Note : En python version < 3.0, il existait deux types distincts int et long...

On peut utiliser la fonction interne int() pour créer des nombres entiers. Elle peut créer des entiers a partir de leur représentation sous forme de chaîne de caractères. On peut aussi spécifier la base.

In [ ]:
entier = int(12)
print(entier)
print(type(entier))
entier = int('13')
print(entier)
print(type(entier))
entier = int('0xFF', 16)
print(entier)
print(type(entier))

Flottants (réels 64 bits)

Pour créer des nombres réels (en virgule flottante), on peut utiliser la fonction interne float().

La précision est limitée à la 16ème décimale.

In [ ]:
pi_approx = 3.1415926535897932
print(pi_approx)
print(type(pi_approx))
print('{:.16f}'.format(pi_approx))
tropgros = float('Infinity')
print(type(tropgros))
print(tropgros)

Attention ! Python autorise un affichage plus long que la précision des flottants mais tous les chiffres après le 16ème chiffre significatif sont faux :

In [ ]:
# On demande 20 chiffres après la virgule, alors que 16 seulement sont exacts
print('{:.20f}'.format(pi_approx))

Attention à ne pas effectuer des opérations interdites...

In [ ]:
# Cette cellule génère une erreur
print(3.14 / 0)
In [ ]:
# Cette cellule génère une erreur
print(34 % 0)
In [ ]:
# Cette cellule génère une erreur
print(27 // 0.0)
In [ ]:
# Cette cellule génère une erreur
print(1 + None)

Complexes

Les nombres complexes, a deux dimensions, peuvent être créés en utilisant le suffixe j à la fin d'un entier ou réel ou en utilisant la fonction interne: complex()

In [ ]:
complexe = 1 + 2j
print('représentation :', complexe)
print(type(complexe))
c = .3j
print(c)

Séquences

Les séquences sont des conteneurs d'objets où les objets référencés sont ordonnés.

Python supporte nativement trois types de séquences :

  • les chaînes de caractères
  • les listes
  • les tuples

Note : De nouveaux types de conteneurs peuvent être créés.

Chaînes de caractères

Pour le traitement de données textuelles, python utilise les chaînes de caractères.

Il existe plusieurs façons de définir une chaîne de caractères.

Pour délimiter le texte on utilise des guillemets (double-quote) ou des apostrophes (single-quote)

In [ ]:
mois1 = 'janvier'
mois2 = "février"
print(mois1, mois2)

Les deux formes sont très utiles car elles permettent d'utiliser des guillemets ou des apostrophes dans des chaîne de caractères de manière simple.

In [ ]:
arbre = "l'olivier"
print(arbre)
cuisson_pates = "huit minutes (8')"
print(cuisson_pates)
record_100m = 'neuf secondes et 58 dixièmes (9"58)'
print(record_100m)

Sinon, pour avoir une apostrophe ou un guillemet dans une chaîne de caractères, il faut le faire précéder d'un \ (backslash). Ce qui est beaucoup moins lisible, mais parfois obligatoire (par exemple une chaîne avec à la fois des guillemets et des apostrophes).

In [ ]:
arbre = 'l\'alisier'
pates = '8\''
record = "9\"58"
print(arbre, pates, record)
duel = 'guillemet: " et apostrophes: \' peuvent être utilisés dans une même chaîne...'
print(duel)
multi = '''Dans une "triplequoted" (voire plus loin), on peut (presque) tout utiliser: `"“ ”,'"«»'"' et ça ne pose pas de problème...'''
print(multi)

Caractères spéciaux

Il est possible de définir des chaînes de caractères qui contiennent des caractères spéciaux. Ils sont introduits par des séquences de deux caractères dont le premier est un \ (backslash). On l'appelle le caractère d'échappement.

  • retour à la ligne : \n
  • tabulation : \t
  • backslash : \\
  • un caractère unicode avec son code : \uXXXX (où les XXXX sont le code hexadécimal représentant ce caractère)

Plus d'information dans la documentation officielle

In [ ]:
print("Une belle présentation, c'est:")
print('\t- bien ordonné')
print('\t- aligné')
print("\t- m\u00EAme s'il y en a plein\nEt c'est plus joli.")

Chaînes multilignes

Pour écrire plusieurs lignes d'une façon plus lisible, il existe les chaînes multilignes :

In [ ]:
# L'équivalent est :
print('''\
Une belle présentation, c'est:
\t- bien ordonné
\t- aligné
\t- même s'il y en a plein
Et c'est plus joli.''')

Exercice : enlevez le caractère \ de la 2ème ligne dans la cellule ci-dessus, et comparez le résultat à celui de la cellule de code précédente (3 cellules plus haut)

Les deux formes de délimiteurs sont aussi utilisables : guillemets triples ou apostrophes triples.

In [ ]:
multi1 = '''m
a
r
s est un mois "multiligne"'''
print(multi1, '\n')

multi2 = """a
v
r
i
l l'est aussi"""
print(multi2)

Unicode

En python 3 , toutes les chaînes de caractères sont unicode, et permettent d'utiliser des alphabets différents, des caractères accentués ou des pictogrammes, etc.

Exemples de caractères spéciaux :

In [ ]:
unicode_str = "Les échecs (♔♕♖♗♘♙), c'est \u263A"
print(unicode_str)
japanese_str = 'Du japonais : ウェブ'
print(japanese_str)
mix_str = '你好 kollha दुनिया'
print('"' + mix_str + '"', 'veut dire: "bonjour tout le monde"')

Pour une liste de caractères unicode, voir ici.

Chaînes spéciales

Il existe d'autres manières plus spécialisées de définir des chaînes de caractères.

Premièrement, des chaînes dans lesquelles les séquences d'échappement ne sont pas remplacées (raw strings = chaînes brutes): r'...', r'''...''', etc.

In [ ]:
normal_str = "chaîne normale: \n'est pas un retour à la ligne, \t pas une tabulation"
print(normal_str)

raw_str = r"chaîne RAW: \n'est pas un retour à la ligne, \t pas une tabulation"
print(raw_str)

Plusieurs chaînes de caractères contigües sont rassemblées (concaténées)

In [ ]:
b = 'a' 'z' 'e' 'r' 't' 'y'
print(b)

On peut mélanger les genres.

In [ ]:
a = 'une chaine ' u"qui est " r'''la somme de ''' """plusieurs morceaux..."""
print(a)

On peut utiliser la fonction str() pour créer une chaîne de caractère à partir d'autres objets.

In [ ]:
a = 23
ch_a = str(a)
print(type(a), a)
print(type(ch_a), repr(ch_a))
a = 3.14
ch_a = str(a)
print(type(a), a)
print(type(ch_a), repr(ch_a))

On ne peut pas mélanger les guillemets et les apostrophes pour délimiter une chaîne de caractères.

In [ ]:
# Cette cellule génère une erreur
a = "azerty'
In [ ]:
# Cette cellule génère une erreur
a = 'azerty"

Exercice : corrigez les deux cellules ci dessus.

Formatage

On peut formater du texte, c'est à dire utiliser une chaîne de caractères qui va servir de modèle pour en fabriquer d'autres. Il y a plusieurs manières de faire cela.

Méthode format()

On utilise la méthode format() d'une chaîne de caractères qui va remplacer les occurences de '{}' par des valeurs qu'on lui spécifie en paramètre. Le type des valeurs passées n'est pas important, une représentation sous forme de chaîne de caractère sera automatiquement créée, avec la fonction str().

'Bonjour {} !'.format('le monde')
In [ ]:
variable_1 = 27
variable_2 = 'vingt huit'
ch_modele = 'Une chaine qui contient un {} ou de multiples ici {} et là {}'
ch_modele.format('toto', variable_1, variable_2) 

Opérateur %

On peut aussi formater du texte avec l'opérateur %. Il va analyser la chaîne à la recherche de caractères '%' et remplacer les marqueurs par le contenu de variables.

Les marqueurs sont donc l'association d'un caractère '%' avec une sequence de caractères décrivant le type de la donnée à intégrer et la manière de formater sa représentation.

  • %d pour des entiers
  • %s pour des chaînes de caractères
  • %f pour des nombres flottants
  • %x pour un nombre entier affiché en base hexadécimale
  • %o pour un nombre entier affiché en base octale
  • %e pour un nombre affiché en notation exponentielle
In [ ]:
import math
a = 27
print('un nombre : %d, une chaîne : %s, un flottant avec une précision spécifiée : %.02f' % (a, 'canal+', math.pi))
print('%x, %x, %x, %x' % (254, 255, 256, 257))
print('%o, %o, %o, %o' % (254, 255, 256, 257))
print('%e' % 2**64)

Attention: Si le type de la donnée passée ne correspond pas à la séquence de formatage (%) python va remonter une erreur.

In [ ]:
# Cette cellule génère une erreur
variable_3 = 'une chaine de caracteres'
# Exemple d'erreur de type: il faut un entier, on a une chaîne de caractères
print('on veut un entier : %d' % variable_3)

On peut se servir de cette fonctionnalité pour tabuler du texte de taille variable.

In [ ]:
ani_mots = ('ane', 'becasse', 'chat', 'dinde', 'elephant')
print('''
Alignons a droite les animaux:
Un animal : %08s.
Un animal : %08s.
Un animal : %18s, qui se croit plus malin que les autres.
Un animal : %08s.
Un animal : %08s.''' % ani_mots)

Exercice : remettez le chat à sa place.

Pour plus d'informations sur le formatage de chaînes de caractères, voir ici et pour la méthode .format() qui tend à remplacer l'utilisation de l'opérateur %, voir .

Listes

Une liste est un objet pouvant contenir d'autres objets. Ces objets sont placés à l'intérieur de façon séquentielle, les uns à la suite des autres. C'est un conteneur dynamique qui peut accueillir de nouveaux éléments ou pouvant rétrécir si on en supprimme.

On crée un liste en délimitant par des crochets [] les éléments qui le composent :

In [ ]:
L = ['egg', 'spam', 'spam', 'spam', 'bacon']
print(L, 'est de type', type(L))

Une liste peut contenir n'importe quel type d'objets.

In [ ]:
L0 = [1, 2]
L2 = [None, True, False, 0, 1, 2**64, 3.14, '', 0+1j, 'abc']
L1 = []
L3 = [[1, 'azerty'], L0]
print(L0, L1)
print(L2)
print(L3)

On peut utiliser la fonction list() pour créer une liste a partir d'autres séquences ou objets.

In [ ]:
a = list()
b = list('bzzzzzt')
print(a)
print(b)

On accède aux éléments d'une liste grâce à un indice. Le premier élément est indicé 0.

In [ ]:
print(L[0])
print(L[4])

Un dépassement d'indice produit une erreur :

In [ ]:
# Cette cellule génère une erreur
print(L[10])

Les listes sont dites mutables : je peux modifier la séquence de ces éléments.

Je remplace le deuxième élément :

In [ ]:
L[1] = 'tomatoes'
print(L)
L[3] = 9
print(L)

Méthodes associées aux listes

Méthodes ne modifiant pas la liste

  • La longueur d'une liste est donnée par fonction len()
  • L.index(elem): renvoie l'indice de l'élément elem (le 1er rencontré)

Méthodes modifiant la liste

  • L.append() : ajouter un élément à la fin
  • L.pop() : renvoie le dernier élément et le retire de la liste
  • L.sort() : trier
  • L.reverse() : inverser

Plus d'infos ici.

In [ ]:
L = ['egg', 'spam', 'spam', 'spam', 'bacon']
print('len() renvoie:', len(L))
L.append('spam') # Ne renvoie pas de valeur
print('Après append():', L)
print('pop() renvoie:', L.pop())
print('Après pop():', L)
L.reverse() # Ne renvoie pas de valeur
print('Après reverse():', L)
print('index() renvoie:', L.index('egg'))
L.remove('spam') # Ne renvoie pas de valeur
print('Après remove:', L)

Pour obtenir la liste des méthodes associées aux listes, on peut utiliser la fonction interne help() :

In [ ]:
help(list) # ou aussi help([])

On peut créer facilement des listes répétitives grâce a l'opération de multiplication.

In [ ]:
a = ['a', 1] * 5
print(a)

Mais on ne peut pas 'diviser' une liste.

In [ ]:
# Cette cellule génère une erreur
a = [1, 2, 3, 4]
print(a / 2)

Exercice : Manipulez la liste L ci-dessous avec les méthodes associées aux listes.

In [ ]:
L = ['egg', 'spam', 'spam', 'spam', 'bacon']
# Votre code ci-dessous

Vous trouverez la documentation complète sur les listes ici.

Tuples

Les Tuples (ou n-uplets en Français) sont des séquences non mutables. On ne peut plus les modifier après leur création.

On les initialise ainsi :

In [ ]:
T = ('a', 'b', 'c')
print(T, 'est de type', type(T))
T = 'a', 'b', 'c'  # une autre façon, en ommettant les parenthèses
print(T, 'est de type', type(T))
T = tuple(['a', 'b', 'c'])  # à partir d'une liste
print(T, 'est de type', type(T))
T = ('a')  # ceci n'est pas un tuple
print(T, 'est de type', type(T))
T = ('a',)  # Syntaxe pour initialiser un tuple contenant un seul élément
print(T, 'est de type', type(T))
T = 'a',  # Syntaxe alternative pour initialiser un tuple contenant un seul élément. Préférez celle avec parenthèses.
print(T, 'est de type', type(T))

Un tuple est dit non-mutable : on ne peut pas en modifier la séquence.

In [ ]:
T = ('a', 'b', 'c')
print(T[1]) # On peut utiliser un élément
In [ ]:
# Cette cellule génère une erreur
T[1] = 'z'  # mais pas le modifier

Intérêt des tuples par rapport aux listes :

  • plus rapide à parcourir que les listes
  • non mutables donc 'protégés'
  • peuvent être utilisés comme clé de dictionnaires (cf. plus loin)

On peut créer des tuples a partir d'autres séquences ou objets grâce à la fonction tuple().

In [ ]:
a = [1, 2, 3, 'toto']
print(type(a), a)
b = tuple(a)
print(type(b), b)
a = 'azerty'
print(type(a), a)
b = tuple(a)
print(type(b), b)

Manipulation des tuples

Construire d'autres tuples par concaténation et multiplication

In [ ]:
T1 = 'a', 'b', 'c'
print('T1 =', T1)
T2 = 'd', 'e'
print('T2 =', T2)
print('T1 + T2 =', T1 + T2)
print('T2 * 3 =', T2 * 3)

Note :

Etant non-mutable l'objet tuple ne peut pas être modifié. Toutefois, s'il est constitué d'éléments mutables, alors ces éléments-là peuvent être modifiés.

Illustration avec un tuple dont un des éléments est une liste :

In [ ]:
T = ('a', ['b', 'c']) # le deuxième élément est une liste donc il est mutable
print('T =', T)
L = T[1]
print('L =', L)
L[0] = 'e'
print('L =', L)
print('T =', T)
In [ ]:
# Ici on fait exactement la même chose...
T = ('a', ['b', 'c'])
print('T =', T)
T[1][0] = 'z'
print('T après =', T)
In [ ]:
# Cette cellule génère une erreur
T[0] = 'A'  # Ici, on essaye de modifier le tuple lui même...

Le slicing de séquences en Python

  • Cela consiste à extraire une sous-séquence à partir d'une séquence.
  • Le slicing fonctionne de manière similaire aux intervalles mathématiques : [début:fin[
  • La borne de fin ne fait pas partie de l'intervalle sélectionné.
  • La syntaxe générale est L[i:j:k], où :
    • i = indice de début
    • j = indice de fin, le premier élément qui n'est pas sélectionné
    • k = le "pas" ou intervalle (s'il est omis alors il vaut 1)
  • La sous-liste sera donc composée de tous les éléments de l’indice i jusqu’à l’indice j-1, par pas de k.
  • La sous-liste est un nouvel objet.

Dans le sens normal (le pas k est positif)

  • Si i est omis alors il vaut 0
  • Si j est omis alors il vaut len(L)

Dans le sens inverse (le pas k est négatif)

  • Si i est omis alors il vaut -1
  • Si j est omis alors il vaut -len(L)-1

Illustrons ça en créant une liste à partir d'une chaîne de caractères.

La fonction split() découpe une chaîne de caractères en morceaux, par défaut en 'mots'.

In [ ]:
L = 'Dans le Python tout est bon'.split()
print(L)

Pour commencer, on extrait de la liste L un nouvel objet liste qui contient tous les éléments de L <=> copie de liste

In [ ]:
print(L[0:len(L):1]) # Cette notation est inutilement lourde car :
print(L[::])         # i = 0, j=len(L) et k=1 donc i, j et k peuvent être omis
print(L[:])          # on peut même ommettre le 2ème ":"

On extrait une sous-liste qui ne contient que les 3 premiers éléments :

In [ ]:
print(L[0:3:1])  # Notation complète
print(L[:3:1])  # Le premier indice vaut i=0, donc on peut l'omettre
print(L[:3])  # Le pas de slicing vaut 1, donc on peut l'omettre, ainsi que le ":"

J'extrais une sous-liste qui exclut les trois premiers éléments :

In [ ]:
print(L[3:len(L):1])  # Cette notation est inutilement lourde car :
print(L[3:])          # j et k peuvent être omis, ainsi que le ":"

Les indices peuvent être négatifs, ce qui permet traiter les derniers éléments :

In [ ]:
# Je veux exclure le dernier élément :
print(L[0:-1:1])  # Notation complète
print(L[:-1:1])  # Le premier indice vaut i=0, donc on peut l'omettre
print(L[:-1])  # Le pas de slicing vaut 1, donc on peut l'omettre

On ne garde que les deux derniers éléments

In [ ]:
print(L[-2:])

Note :

L[1] n'est pas équivalent à L[1:2], ni à L[1:], ni à L[:1].

Illustration :

In [ ]:
a = L[1]
print(type(a), a) # Je récupère le deuxième élément de la liste
a = L[1:2]
print(type(a), a) # Je récupère une liste composée du seul élément L[1]
a = L[1:]
print(type(a), a) # Je récupère une liste
a = L[:1]
print(type(a), a) # Je récupère une liste

Exercice : Retourner une liste composée des éléments de L en ordre inverse avec une opération de slicing. Toute utilisation de [].reverse() ou reversed() est interdite.

In [ ]:
L = 'Dans le Python tout est bon'.split()
print(L)
# <- votre code ici

Solution : exos/reverse.py

Le slicing peut être utilisé pour modifier une séquence mutable, gâce à l'opération d'assignation.

In [ ]:
L = 'Dans le Python tout est bon'.split()
print(L)
L[2:4] = ['nouvelles', 'valeurs', 'et encore plus...', 1, 2, 3]
print(L)

Le slicing peut être utilisé sur des chaînes de caractères.

In [ ]:
alphabet = 'abcdefghijklmnopqrstuvwxyz'
print(alphabet[:4], alphabet[-4:], alphabet[0:12:3])

Exercice:

  1. Découpez l'alphabet en deux parties égales
  2. Prenez une lettre sur deux
In [ ]:
# Votre code ici

Solution : exos/alphabet.py

Chaînes de caractères, le retour

Les chaînes de caractères sont considérées comme des séquences non mutables et l'on peut les manipuler comme telles.

In [ ]:
# Cette cellule génère une erreur
non_mutable = 'abcdefgh'
non_mutable[3] = 'D'

Il faut construire une nouvelle chaîne de caractère. En concaténant des morceaux (slices) de la chaîne originale:

In [ ]:
nouvelle_chaine = non_mutable[:3] + 'D' + non_mutable[4:]
print(nouvelle_chaine)

Ou alors en utilisant une transformation en liste, puis a nouveau en chaîne:

In [ ]:
a = list(non_mutable)
a[3] = 'D'
print(''.join(a))

On peut savoir si une chaîne se trouve dans une autre

In [ ]:
print('123' in 'azerty_123_uiop')
print('AZE' in 'azerty_123_uiop')
print('aze' in 'azerty_123_uiop')

La longueur d'une chaîne s'obtient avec len().

In [ ]:
print(len(non_mutable))

Exercice, dans la cellule ci-dessous:

  1. Insérez le caractère '#' au milieu de la chaîne donnée.
  2. Idem mais coupez la chaine en 3 parties, et insérez le caractère '@' entre chacune d'elles.
  3. Insérez le caractère '|' entre chaque caractère de la chaîne.
In [ ]:
chaine_donnee = 'azertyuioppoiuytreza'
# Votre code ici

Les dictionnaires

Les listes associatives sont des conteneurs où les objets ne sont pas ordonnés ni accessibles par un indice mais sont associés à une clé d'accès.

L'accès aux éléments se fait comme pour les listes ou tuples, avec les [], mais vous pouvez utiliser (presque) n'importe quelle valeur comme clé.

dico = {<clé1>: <valeur1>[, <clé2>: <valeur2>]...}

Les clés doivent être des objets non mutables. Les listes ne peuvent pas servir de clés alors que les tuples le peuvent.

Dans dico, on accède à valeur1 avec la syntaxe dico[clé1].

Un exemple

In [ ]:
dic_animaux = {'ane': True, 'arbre': False, 'chat': True, 'lune': False, 'humain': True}
cle = 'chat'
valeur = dic_animaux[cle]
print(valeur)
print('{} est un animal: {}'.format(cle, valeur))
# Ou encore
print('{} est un animal: {}'.format('chat', dic_animaux['chat']))

Exercice : essayez de savoir si un arbre est un animal

Solution : exos/animarbre.py

Les différentes manières de créer des dictionnaires:

In [ ]:
a = {'un': 1, 'deux': 2, 'trois': 3}  # Les accolades comme syntaxe
b = dict(un=1, deux=2, trois=3)  # La méthode dict()
c = dict(zip(['un', 'deux', 'trois'], [1, 2, 3]))  # On "zippe" deux listes
d = dict([('deux', 2), ('un', 1), ('trois', 3)])  # On transforme une liste de 2-tuples
e = dict({'trois': 3, 'un': 1, 'deux': 2})
a == b == c == d == e

La fonction interne [dict() permet de créer des dictionnaires de diverses manières.

Accéder à un élément qui n'est pas dans le dictionnaire génère une erreur. Il existe la méthode {}.get() ou l'opérateur in qui permettent de ne pas rencontrer ce problème.

In [ ]:
# Cette cellule génère une erreur
err = a['quatre']

Ici on utilise .get() et cela ne remonte pas d'erreur.

In [ ]:
print(a.get('quatre'))    # La valeur par défaut est 'None' lorsque .get() ne trouve pas l'élément
print(a.get('quatre', 5)) # On peut spécifier une autre valeur par défaut

Un autre exemple

In [ ]:
tup_mois = ('jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec')
tup_long = (31, (28, 29), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
dic_mois = dict(zip(tup_mois, tup_long))
mois_naissance = 'jun'
print('Il y a %d jours dans votre mois de naissance' % dic_mois[mois_naissance])

Exercice:

  1. Modifiez la cellule précédente pour y changer mois_naissance (les 3 premiers caractères de votre mois de naissance, en anglais). Ré-exécutez la cellule et vérifiez la réponse.
  2. Un problème s'est glissé dans la cellule, lequel ?
  3. Corrigez-le. (il y a plusieur manières de faire)
  4. Les noms de mois raccourcis sont en anglais et non en français, pourquoi ?
  5. Utilisez input('En quel mois êtes-vous né(e) ? ') pour initialiser mois_naissance et constatez le gain de qualité en IHM (Interface Homme Machine, ergonomie).

Solution : exos/dict_anniv.py

Les dictionnaires sont mutables.

In [ ]:
ages = {'albert': 62, 'bob': 34, 'charlie': 1, 'daphne': 67}
print(ages)
# C'est l'anniversaire de charlie, il a un an de plus...
ages['charlie'] += 1
print(ages)
print('Albert a %d ans.' % ages['albert'])
# Bob est parti, enlevons-le
del ages['bob']
print(ages)
  • Savoir si une clé est présente dans un dictionnaire est une opération rapide. On utilise, comme pour les séquences, l'opérateur in.
  • La fonction interne len() est utilisable pour savoir combien d'objets sont référencés dans le dictionnaire.
In [ ]:
ages = {'albert': 62, 'bob': 34, 'charlie': 1, 'daphne': 67}
print('Charlie est dedans ?', 'charlie' in ages)
print('Zoé est dedans ?', 'zoé' in ages)
print('Bob est dedans ?', 'bob' in ages)
print('Il y a %d personnes.' % len(ages))
# Bob est parti, enlevons-le
del ages['bob']
print('Bob est dedans ?', 'bob' in ages)
print('Il y a %d personnes.' % len(ages))

On peut itérer sur les clés ou les objets référencés, ou vider un dictionnaire, en comparer deux, etc.

Pour plus d'informations sur les dictionnaires, voir ici.

Exercice :

  1. Créez un dictionnaire qui va traduire des chiffres (de 0 à 9) écrits en toutes lettres entre deux langues Par exemple : trad_num['un'] -> 'one'
  2. Modifiez ce dictionnaire, pour qu'il fonctionne dans les deux sens de traduction (Fr -> En et En -> Fr)
  3. Modifiez ce dictionnaire, pour qu'il fonctionne aussi avec les chiffres sous forme d'entiers Par exemple : trad_num[1] -> 'un'
In [ ]:
# Votre code ici

Solution : exos/trad_num.py

Les ensembles

Les ensembles sont des conteneurs qui n'autorisent pas de duplication d'objets référencés, contrairement aux listes et tuples.

On peut créer des ensembles de cette façon :

ensemble = set(<iterable>)

<iterable> peut être n'importe quel objet qui supporte l'itération : liste, tuple, dictionnaire, un autre set (pour en faire une copie), vos propres objets itérables, etc...

Tout comme pour les dictionnaires, l'opérateur in est efficace. La fonction set() permet de créer des ensembles.

In [ ]:
list1 = [1, 1, 2]
tupl1 = ('un', 'un', 'deux', 1, 3)

b = set(list1)
a = set(tupl1)

print(a, b)

print('''La chaîne 'un' est elle dans l'ensemble ?''', 'un' in a)
a.remove('un')
print('''La chaîne 'un' est-elle toujours dans l'ensemble ?''', 'un' in a)

print(a, b)

Des opérations supplémentaires sont possibles sur des ensembles. Elles sont calquées sur les opérations mathématiques :

  • union
  • intersection
  • etc...
In [ ]:
print('intersection :', a & b)
print('union :', a | b)

Pour plus d'informations sur les ensembles, voir ici

Fichiers

Ouverture

L'instruction :

f = open('interessant.txt', mode='r')

ouvre le fichier interessant.txt en mode lecture seule et le renvoie dans l'objet f.

On peut spécifier un chemin d'accès complet ou relatif au répertoire courant. Le caractère de séparation pour les répertoires peut être différent en fonction du système d'exploitation ('/' pour unix et '\' pour windows), voir le module os.path.

Modes d'ouverture communs

  • 'r' : lecture seule
  • 'w' : écriture seule
  • 'a' : ajout à partir de la fin du fichier

Note : Avec 'w' et 'a', le fichier est créé s'il n'existe pas.

Pour plus d'informations sur les objets fichiers, voir ici, pour la documentation de la fonction open(), voir .

Fermeture

On ferme le fichier f avec l'instruction :

f.close()

Méthodes de lecture

  • f.read() : retourne tout le contenu de f sous la forme d’une chaîne de caractères.
In [ ]:
f = open('interessant.txt', mode='r')
texte = f.read()
print('"texte" est un objet de type', type(texte), 'de longueur', len(texte), 'caractères:')
print(texte)
print('Contenu en raw string:')
print(repr(texte))
f.close()
  • f.readlines() : retourne toutes les lignes de f sous la forme d’une liste de chaînes de caractères.
In [ ]:
f = open('interessant.txt', mode='r')
lignes = f.readlines()
print('"lignes" est un objet de type', type(lignes), 'contenant', len(lignes), 'éléments:')
print(lignes)
f.close()

Méthodes d'écriture

  • f.write('du texte') : écrit la chaine 'du texte' dans f
In [ ]:
chaine = 'Je sais écrire\n...\navec Python !\n'
# mode 'w' : on écrase le contenu du fichier s'il existe
# encoding UTF-8: on peut écrire des chaînes avec des caractères non ASCII
f = open('pas_mal.txt', mode='w', encoding='utf8')
f.write(chaine)
f.close()

Note : du point de vue du système, rien n'est écrit dans le fichier avant l’appel de f.close()

  • f.writelines(ma_sequence) : écrit la séquence ma_sequence dans f en mettant bout à bout les éléments
In [ ]:
sequence = ['Je sais ajouter\n', 'du texte\n', 'avec Python !\n']
f = open('pas_mal.txt', mode='a')
# mode 'a' : on ajoute à la fin du fichier
# encoding par défaut: uniquement des caractères ASCII
f.writelines(sequence)
f.close()
In [ ]:
chaine = 'Pour ajouter du texte avec des caractères accentués: ï\n'
f = open('pas_mal.txt', mode='a', encoding='utf8')
# mode 'a' : on ajoute à la fin du fichier
# encoding UTF-8: on peut écrire des chaînes avec des caractères non ASCII
f.write(chaine)
f.close()

Exercice :

  1. écrire le contenu de la liste mystere dans le fichier coded.txt puis fermer ce dernier
  2. lire le fichier coded.txt et le stocker dans une chaine coded
  3. Décoder la chaîne coded avec les instructions suivantes:
    import codecs
    decoded = codecs.decode(coded, encoding='rot13')
  4. écrire la chaine decoded dans le fichier decoded.txt et fermer ce dernier
  5. visualiser le contenu du fichier decoded.txt dans un éditeur de texte
In [ ]:
mystere = ['Gur Mra bs Clguba, ol Gvz Crgref\n\n',
           'Ornhgvshy vf orggre guna htyl.\n',
           'Rkcyvpvg vf orggre guna vzcyvpvg.\n']
# Votre code ci-dessous

Solution : exos/fichiers.py