Choisir un des projets suivants :
Créé en 1991 par Guido Van Rossum, un fan des Monty Python.
Plus ancien que PHP, Java, JavaScript, .Net
Pourtant bien plus simple et (discutablement) plus complet
Python, un langage impératif (on lui donne des ordres), interprété (on ne compile pas) à typage dynamique (on ne précise pas les types aux variables)
⇒ 10 × plus rapide pour coder qu’avec un langage compilé à typage statique comme C
Langage multi-paradigme, on peut programmer de nombreuses manières : programmation fonctionnelle, orientée objet, orientée événements, asynchrone, etc.
Un langage pour se concentrer sur ce qu’on cherche à faire, en étant le moins possible perturbé par des contraintes techniques
Une des communautés open source les plus actives, compétentes et bienveillantes.
Facile pour débuter, mais reste pertinent pour des travaux experts
Permet d’écrire tout type de programme
Contient une librairie standard particulièrement complète
Possède un écosystème de paquets extrêmement vaste pour réaliser les tâches les plus complexes
Basé sur une philosophie incitant à la simplicité et à la clarté.
Un poème, Le Zen de Python, résume cette philosophie.
Et open source, donc :
Utilisé dans le monde entier comme couteau suisse de la programmation. Second langage le plus utilisé en open source après JavaScript.
On s’en sert pour faire :
Commence à être indispensable en informatique aujourd’hui, et est utilisé par les plus grands :
On utilise au minimum la version 3.4.
Prendre la version la plus récente, par exemple 3.6.4.
Ouvrir un terminal et lancer :
sudo apt install python3.6
Si le paquet n’existe pas vous devez utiliser une version plus ancienne, essayer en remplaçant 3.6
par 3.5
ou 3.4
.
Télécharger sur python.org puis installer le programme.
Télécharger sur python.org puis lancer le fichier téléchargé, et penser à cocher Add Python 3.6 to PATH
pendant l’installation. Redémarrer l’ordinateur parce que Windows.
Quelque soit le système, lancer un terminal (nommé « Invite de commandes » sous Windows).
Pour lancer Python en mode interactif, utiliser la commande :
python3.6
Après plusieurs lignes d’informations, on voit un triple chevron >>>
.
Cela indique que Python attend que vous saisissiez une commande Python.
Plus tard, on créera des fichiers .py contenant du Python, qu’on exécutera en mode non-interactif en faisant :
python3.6 un_programme.py
Python utilise de nombreux termes, et ce n’est jamais à la légère. Chaque terme a une définition bien précise. Quelques exemples :
En cas de toute sur un terme technique, se référer systématiquement au glossaire officiel.
Les données manipulées en Python ont des types divers.
Des dizaines de types, mais nous nous servirons d’abord des types simples suivants :
Nom du type en Python | Notation | |
---|---|---|
Nombre entier | int |
1234567 |
Nombre à virgule | float |
3.14 |
Chaîne de caractères | str |
'abc' ou "abc" |
Chaîne de caractères binaire | bytes |
b'abc' ou b"abc" |
Booléen (« oui » ou « non ») | bool |
True ou False |
Valeur spéciale unique pour dire « rien » | NoneType |
None |
Attention : les nombres à virgule s’écrivent… sans virgule ! Il s’agit de la notation anglo-saxonne, avec un point à la place de la virgule.
En Python comme en mathématiques, des symboles existent pour effectuer des opérations.
Heureusement, ils sont beaucoup moins nombreux, et certains sont déjà familiers.
Ces opérations s’exécutent indifféremment sur des nombres entiers ou à virgule.
Opération | Notation | Résultat |
---|---|---|
Addition | 7 + 2 |
9 |
Soustraction | 7 - 2 |
5 |
Multiplication | 7 * 2 |
14 |
Division | 7 / 2 |
3.5 |
Modulo (reste d’une division euclidienne) | 7 % 2 |
1 |
Quotient d’une division euclidienne | 7 // 2 |
3 |
Puissance | 7 ** 2 |
49 |
Pour regrouper des opérations, on utilise des parenthèses, comme en mathématiques :
((3 + 8) * (5.5 - 7)) / 3
En Python, ces opérations arithmétiques fonctionnent aussi sur d’autres types.
Certains opérateurs marchent notamment sur les chaînes de caractères.
Voici ce que cela donne :
Opération | Résultat |
---|---|
'abc' + 'def' |
'abcdef' |
'abc' - 'def' |
Opération impossible ! |
'abc' * 'def' |
Opération impossible ! |
'abc' * 3 |
'abcabcabc' |
'abc' / 'def' |
Opération impossible ! |
'abc' / 3 |
Opération impossible ! |
En informatique, une variable est un endroit nommé où on stocke une donnée.
En Python, on écrit d’abord le nom de la variable, puis le symbole =
, puis la donnée :
nom = 'Vivaldi'
On dit alors qu’on assigne la chaîne de caractères 'Vivaldi'
à la variable nom
.
Attention, ce n’est pas une égalité mathématique ! On peut très bien écrire :
n = 1
n = 2
Cela signifie qu’on assigne 1
à la variable n
, puis qu’on assigne 2
à cette même variable. Après la seconde ligne, n
vaut 2
, cela écrase l’opération précédente, comme lorsqu’on écrase un fichier avec un fichier du même nom.
Un nom de variable peut contenir des lettres, des chiffres ou des underscores mais ne peut commencer par un chiffre. Il peut stocker le résultat d’un calcul. Exemple :
mon_budget_2016 = (12 * 30) + 5
À noter, dans les dernière versions de Python, on peut préciser un type aux variables à titre informatif :
n: int = 3
Ne pas hésiter à le faire si cela vous aide, mais vous pouvez vous en passer.
Comme en mathématiques, une fonction en programmation permet de transformer des paramètres en un résultat. Pour utiliser une fonction, il faut écrire le nom de la fonction suivi de parenthèses contenant des paramètres séparés par des virgules. Exemple :
print(1, 2, 'abc')
Cette fonction, print
, permet d’afficher les paramètres dans la console.
À noter, cette fonction est en réalité ce qu’on appelle une procédure en algorithmique, terme que l’on n’utilise pas en Python.
Une autre fonction, input
, permet de demander à l’utilisateur de saisir du texte, qu’on peut stocker :
desir = input('Que voulez-vous ? ')
Les fonctions utilisables directement sont toutes listées sur docs.python.org/3/library/functions.
Seules ces fonctions sont utiles pour commencer :
Fonction | Utilité | Fonction | Utilité |
---|---|---|---|
float |
Convertit le paramètre en nombre à virgule | list |
Convertit une donnée en liste |
input |
Voir précédemment | min |
Donne le plus petit de tous les paramètres |
int |
Convertit le paramètre en nombre entier | max |
Donne le plus grand de tous les paramètres |
len |
Renvoie la longueur d’une donnée | print |
Voir précédemment |
(Toujours dans la console interactive)
Effectuer les tâches suivantes :
age
futur_age
futur_age
Les listes permettent de stocker des séries ordonnées de données, et se définissent avec des crochets :
premiers = [1, 2, 3, 5, 7, 11]
liste_mixte = [1, 1.5, 'a', True, None]
Connaître le nombre d’éléments d’une liste en utilisant la fonction len vue auparavant :
len(premiers) # Renvoie 6
Obtenir un élément de la liste (en commençant par 0 et non 1) :
premiers[0] # Renvoie 1
premiers[3] # Renvoie 5
Tester la présence d’un élément :
'violon' in liste_mixte # Renvoie False
(Toujours dans la console interactive)
Effectuer les instructions suivantes :
'bravo'
'Chuck Norris'
est dans la liste (on ne sait jamais…)Comme une liste, mais pour faire correspondre des données entre elles.
Ici, on fait correspondre des prénoms (les clés) à des âges (les valeurs) :
ages = {'Paul': 38, 'Aziz': 49, 'Shotaro': 22}
Connaître le nombre d’entrées :
len(ages) # Renvoie 3
Obtenir une valeur à partir d’une clé :
ages['Paul'] # Renvoie 38
Ajouter une entrée au dictionnaire :
ages['Antonio'] = 63
Supprimer une entrée du dictionnaire :
del ages['Paul']
Vérifier si une clé est dans le dictionnaire :
'Hans' in ages # Renvoie False
(Toujours dans la console interactive)
Effectuer les instructions suivantes :
achats
, dans lequel on fera correspondre des noms d’objets à des nombres à virgule indiquant le prix d’achat d’un objet.En Python, les types de données se classent en deux grandes catégories :
Exemple :
In [1]:
l = [1, 2, 3]
print(id(l), l) # id renvoie l’adresse mémoire de l’objet
del l[0]
print(id(l), l) # L’adresse mémoire est la même, c’est le même objet
In [2]:
s = 'abc'
print(id(s), s)
s += 'def'
print(id(s), s) # L’adresse mémoire est différente, ce n’est pas le même
Voici un récapilatif des types, selon s’ils sont mutables ou immutables. Sur une même ligne figurent les équivalents. Par exemple, str
n’a pas d’équivalent mutable. list
a l’équivalent immutable tuple
. dict
n’a pas d’équivalent immutable.
Immutable | Mutable |
---|---|
str |
|
bytes |
|
int |
|
float |
|
bool |
|
NoneType |
|
tuple |
list |
dict |
|
frozenset |
set |
tuple
, frozenset
et set
sont des types moins souvent utilisés pour débuter Python. Un tuple
s’écrit (1, 2, 3)
et est comme une liste non modifiable. Un set
est un ensemble de données qui supprime automatiquement les doublons et s’écrit set([1, 2, 3])
. frozenset
fonctionne pareil, mais n’est pas modifiable.
Pour exécuter du code uniquement si une condition est vraie, on utilise la commande if
suivie de la condition. Par exemple ici, « bingo » ne sera affiché que si x
est supérieur à 3 :
if x > 3:
print('bingo')
Notez qu’on indente de 4 espaces ce qui est exécuté si la commande est vraie.
Deux types d’opérateurs pour les conditions, les comparaisons et opérateurs booléens (ou combinaisons).
Type d’opération | Opération | Notation |
---|---|---|
Comparaison | a égal à b |
a == b |
Comparaison | a différent de b |
a != b |
Comparaison | a supérieur à b |
a > b |
Comparaison | a supérieur ou égal à b |
a >= b |
Comparaison | a inférieur à b |
a < b |
Comparaison | a inférieur ou égal à b |
a <= b |
Combinaison | a ou b |
a or b |
Combinaison | a et b |
a and b |
Combinaison | opposé de a |
not a |
Les comparaisons prennent deux valeurs quelconques, les opérandes, et renvoient un booléen, par exemple :
3 > 1 # renvoie True
'a' == 'b' # renvoie False
Les combinaisons permettent de combiner des booléens, donc de combiner le résultat de comparaisons :
3 > 1 or 'a' == 'a' # renvoie True puisque l’une des deux comparaisons vaut True
On peut mettre des parenthèses pour expliquer à Python la priorité des opérations :
(3 > 1 or 'a' == 'a') and 5 <= 2 # renvoie False, tandis que
3 > 1 or ('a' == 'a' and 5 <= 2) # renvoie True
Voici un résumé du comportement des opérateurs booléens :
True or True # True
True or False # True
False or True # True
False or False # False
True and True # True
True and False # False
False and True # False
False and False # False
not True # False
not False # True
In [3]:
if 1 > 3:
print('Condition vraie')
else:
print('Condition fausse')
On peut aussi tester une autre condition à l’aide de la contraction de “else if”, le mot-clé elif
:
In [4]:
if 1 > 3:
print('1re condition vraie')
elif 2 > 3:
print('2de condition vraie')
elif 5 > 3:
print('3e condition vraie')
else:
print('Tout est faux')
Créer un fichier texte vide conditions.py
À l’intérieur du fichier, créer une variable age
contenant votre âge
Créer une variable pointure
contenant votre pointure de chaussure
Écrire une condition affichant « Vous êtes mineur » si vous avez moins de 18 ans
Sinon vérifier si votre pointure vaut plus de 2 fois votre âge et que votre âge est pair, et si tout cela est vrai, afficher « Vous êtes un majeur veinard »
Sinon afficher « Vous êtes un majeur et malchanceux »
Deux types de boucles en Python : for
et while
.
while
répète les mêmes lignes de code tant qu’une condition reste vraiefor
passe en revue le contenu d’une liste (ou similaire) et s’arrête lorsqu’il n’y a plus rienDeux exemples équivalents affichant tous deux 0
, 1
et 2
:
i = 0
while i < 3:
print(i)
i += 1 # Raccourci pour i = i + 1
for i in [0, 1, 2]:
print(i)
for
est très prisé dans l’univers Python pour sa simplicité, mais dans certains cas while
est plus adapté.
Il existe une fonction range
permettant d’écrire plus rapidement une suite de nombres consécutifs dans une boucle for
. Par exemple, range(10)
équivaudra à itérer sur [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
et range(3, 6)
équivaudra à itérer sur [3, 4, 5]
.
Dans un fichier boucles.py
, créer deux boucles :
Une boucle affichant des nombres de 50 à 100 inclus
Une boucle demandant à l’utilisateur « Quel est votre prénom ? » jusqu’à ce qu’il tape exactement votre prénom.
À chaque fois que cela ne correspondra pas à votre prénom, afficher « Accès refusé »
Python inclut des dizaines de modules indispensables à la vie du développeur.
Pour importer un module entier et s’en servir, il faut utiliser la syntaxe :
import random
random.randint(5, 20) # Choisit un nombre aléatoire entre 5 et 20.
Pour importer directement un composant d’un module, comme une fonction, il faut utiliser la syntaxe :
from random import randint
randint(5, 20)
Par convention, toutes les importations sont faites en haut du fichier et sont groupées par ordre alphabétique de nom de module, par exemple :
from math import log
from random import randint, choice
import re
from time import time
La documentation de tous les modules inclus dans Python est sur :
docs.python.org/3/library/
Depuis 8 ans, deux versions principales de Python coexistent : Python 2 et Python 3.
Python 3 est né de la volonté de changer de nombreux choix de Python qui ne pouvaient être changés du jour au lendemain.
Cette coexistence a permi à la communauté de prendre le temps de s’approprier tous ces changements et de rendre les paquets compatibles avec la nouvelle version, Python 3.
Aujourd’hui, nous approchons de la fin de cette période de transition et vous pouvez travailler directement avec Python 3, peut-être n’aurez-vous d’ailleurs jamais à utiliser Python 2.
Si jamais vous avez besoin d’utiliser Python 2, les différences majeures sont :
print
n’était pas une fonction et s’écrivait donc sans parenthèses : print 'quelque chose'
# coding: utf-8
et ajouter un petit U avant chaque chaîne unicode, comme u'chaîne accentuée'
1 / 2
renvoyait 0
et non 0.5
input
avait un comportement différent et l’équivalent du input
de Python 3 s’appellait raw_input
Les autres différences sont assez avancées et il est finalement rare de les croiser.
En informatique, on est amenés à utiliser des versions différentes de logiciels pour chaque projet.
Un environnement virtuel Python, ou “virtualenv”, permet d’avoir pour chaque projet un ensemble de paquets Python différent des autres projets.
Installation sous Ubuntu :
sudo apt install virtualenvwrapper python3-virtualenv
echo 'export WORKON_HOME=~/.virtualenvs' >> ~/.bashrc
Redémarrer la console
Créer un virtualenv :
mkvirtualenv -p /usr/bin/python3.5 nom_du_virtualenv
Activer un virtualenv :
workon nom_du_virtualenv
Désactiver le virtualenv actuel :
deactivate
Supprimer un virtualenv :
rmvirtualenv nom_du_virtualenv
Une fois dans un virtualenv, la commande pip
permet d’installer/désinstaller des paquets.
Installer puis désinstaller un paquet :
pip install Django
pip uninstall Django
Lister les paquets installés :
pip freeze
Installer une version spécifique d’un paquet (on échappe avec des guillemets car on utilise souvent des caractères spéciaux de ligne de commande pour préciser la version) :
pip install "django-cachalot==1.5.0"
Installer un paquet avec la dernière version dans une fourchette de versions :
pip install "Django>=1.10,<1.11"
Rechercher tous les paquets contenant un mot dans leur nom :
pip search django
Tous ces paquets proviennent du PyPI (Python Package Index) : pypi.python.org
In [5]:
def calcul(x, y):
return x ** 2 + 3 * y + 2
def
indique qu’on définit une fonction.calcul
.x
et y
: comme des variables, mais définies implicitement.return
.
In [6]:
print(calcul(5, 23))
Une fonction peut :
return
, elle renverra None
par défaut (ce qu’on appelle procédure en algorithmique est donc appellé aussi fonction en Python)Exemple plus complexe :
def calcul_dur(a, b=0, c=1):
if b == 0:
return a
d = a / b + c
return d * 2
Ici, b
et c
sont des arguments optionnels, si on ne les spécifie pas ils vaudront 0
et 1
.
Exemples d’utilisation :
calcul_dur(1) # Renvoie 1
calcul_dur(1, 2, 3) # Renvoie 7.0
calcul_dur(2, b=3, c=4) # Renvoie 9.3333…
calcul_dur(2, c=4) # Renvoie 2
calcul_dur(2, c=4, b=3) # Renvoie 9.3333…
On peut donc préciser le nom des arguments optionnels pour :
À partir de maintenant, toujours faire les exercices dans des fichiers Python, ici par exemple fonctions.py
.
Créer une fonction square
transformant un entier x
en son carré.
Créer une fonction salut
avec un argument prenom
et affichant « Salut Michel ! Ça va ? » en remplaçant le prénom.
Modifier la fonction précédente pour qu’elle accepte un argument optionnel booléen forme_politesse
permettant de déterminer si on écrit « Salut Michel ! Ça va ? » ou « Bonjour Michel ! Comment allez-vous ? ».
Par défaut, afficher la forme de politesse.
Ajouter un argument optionnel chaîne de caractères titre
contenant par exemple 'M.'
, 'Mme'
, 'Dr'
, 'mon'
ou 'ma'
. Par défaut, cet argument vaut None
. Le titre doit s’afficher de sorte que les chaînes affichent « Bonjour Dr. Michel ! Comment allez-vous ? » ou « Salut mon Michel ! Ça va ? ». Si cet argument vaut None
, on affiche la forme du point précédent : « Salut Michel ! Ça va ? ».
Utiliser la fonction pour afficher :
« Bonjour M. Pierre ! Comment allez-vous ? »
« Salut cher Patrice ! Ça va ? »
« Salut Jean-Claude ! Ça va ? »
In [7]:
def f(*args):
print(args)
f(1, 2, 3)
In [8]:
def f(**kwargs):
print(kwargs)
f(a=1, b=2, c=3)
On peut bien entendu combiner positionnels et optionnels :
In [9]:
def f(*args, **kwargs):
print(args, kwargs)
f(1, 2, 3, a=4, b=5, c=6)
In [10]:
s = 'abcdef'
print(s[0:3])
print(s[:3]) # Équivalent à [0:3]
print(s[-3:-1]) # -1 signifie l’avant dernier caractère
print(s[-3:]) # Pas de fin = jusqu’à la fin
print(s[::2]) # Le troisième « argument », optionel, est le pas
print(s[:]) # Copie la séquence
Cela fonctionne de la même manière avec d’autres types de séquences :
In [11]:
l = [1, 2, 3, 4, 5, 6]
print(l[:4:2])
On va créer un système permettant de chiffrer et déchiffrer un message tapé par un utilisateur.
Ce système comprendra deux fonctions, cipher
et decipher
.
cipher
va piocher un caractère sur deux et les coller, puis prendre les caractères restants, inverser leur ordre, et les ajouter à la suite. Pour chiffrer '0123456789'
, on prend donc '02468'
. On prend les caractères restants, '13579'
, dont on inverse l’ordre pour obtenir '97531'
. Et enfin on colle l’ensemble pour obtenir '0246897531'
.
decipher
va faire l’opération inverse pour récupérer le message original.
Exemple d’utilisation :
In [12]:
from math import ceil
from itertools import zip_longest
def cipher(s):
return s[::2] + s[1::2][::-1]
def decipher(s):
half = ceil(len(s) / 2)
groups = zip_longest(s[:half], s[half:][::-1], fillvalue='')
return ''.join(a + b for a, b in groups)
In [13]:
text = 'Python envoie du lourd'
ciphered = cipher(text)
print(ciphered)
print(decipher(ciphered))
Écrire la fonction cipher
.
Elle doit être faite en deux lignes de moins de 80 caractères (y compris la déclaration de fonction). Aucune librairie n’est nécessaire.
Écrire la fonction decipher
.
Cette fonction est nettement plus difficile, et doit être faite en 4 à 8 lignes de moins de 80 caractères.
Pour cette fonction. Cela peut être fait sans librairie externe, mais il est vivement conseillé d’utiliser les fonctions math.ceil
et itertools.zip_longest
.
Ce qu’on appelle un module est un fichier Python ou un dossier regroupant de nombreux fichiers Python.
On utilise le terme paquet pour désigner un dossier regroupant de nombreux fichiers Python.
Un paquet contient obligatoirement un fichier __init__.py
, même vide.
On utilise également ce terme pour désigner une librairie externe installable depuis le Python Package Index, que ce soit en réalité un paquet ou un module.
Le terme librairie est utilisé pour désigner tout module externe au projet dans lequel on travaille, généralement installée depuis PyPI.
Pour résumer :
⇒ C’est un peu le bazar, c’est vrai.
Créer un fichier essai.py
contenant la ligne truc = 3
Lancer la console Python dans le dossier contenant essai.py
puis exécuter :
from essai import truc
print(truc)
3
doit donc être affiché !
De même, créer une fonction quelconque dans le fichier essai.py
, importer et utiliser cette fonction.
Un paquet Python est un dossier contenant des fichiers Python.
Créer un dossier paquet_test
contenant les fichiers __init__.py
, a.py
et b.py
.
Dans a.py
, créer une variable var_a
et une fonction quelconque func_a
.
Dans b.py
, créer une variable var_b
et une fonction quelconque func_b
.
Dans __init__.py
, écrire :
from .a import var_a, func_a # Le . montre que l’import est relatif
from .b import var_b, func_b
Lancer la console Python dans le dossier contenant paquet_test
, puis exécuter :
from paquet_test.a import var_a
from paquet_test import func_a, var_b
Utiliser les objets importés et constater que l’import fonctionne !
Tout est objet en Python (ou presque).
Les méthodes sont des fonctions appliquées à un objet et correspondant à leur type. Exemples :
'BonJour'.lower() # 'bonjour'
'27'.isdigit() # True
3.7.is_integer() # False
3.0.is_integer() # True
x = 8 / 3
x.is_integer() # False
une_liste = []
une_liste.append(1678) # Ajoute 1678 à la liste
Convertir une entrée utilisateur en minuscules puis en majuscules, et afficher les deux.
Définir une liste vide, puis y ajouter 3 entrées utilisateur différentes converties en majuscules, puis afficher la liste.
Définir une liste vide, puis y ajouter 3 nombres entiers saisis par l’utilisateur. On testera si l’entrée utilisateur est bien un nombre avant de l’ajouter à la liste. Afficher la liste.
Il existe deux principaux outils en Python pour formater des chaînes de caractères :
%
, utilisant la même syntaxe qu’en C et nombre d’autres langages.format()
, plus facile et complet, mais moins rapideQuelques exemples d’équivalents :
% |
.format() |
Résultat |
---|---|---|
'J’ai %s' % '28 ans' |
'J’ai {}'.format('28 ans') |
J’ai 28 ans |
'%d %s' % (28, 'ans') |
'{} {}'.format(28, 'ans') |
28 ans |
'%(age)d ans' % {'age': 28} |
'{age} ans'.format(age=28) |
28 ans |
pyformat.info récapitule parfaitement la différence et toutes les possibilités des deux outils, avec moult exemples.
Depuis Python 3.6, on peut utiliser les formatted strings ou f-strings pour utiliser .format()
plus simplement :
In [14]:
age = 28
texte = 'ans'
print(f'{age} {texte}')
Écrire une fonction random_table
effectuant ceci :
n
chaînes de caractères aléatoires de 1 à 30 caractères alphabétiques maximum. Ces chaînes de caractères peuvent contenir des espaces.Exemple :
In [15]:
from random import choice, uniform, randint
from string import ascii_lowercase
CHARS = ascii_lowercase + ' '
def random_table(size):
for i in range(size):
s = ''.join([choice(CHARS)
for i in range(randint(1, 30))])
print('%-30s | %7.1f' % (s.lstrip().capitalize(),
uniform(-1000, 1000)))
In [16]:
random_table(10)
Des erreurs arrivent, cela ne doit pas être une fatalité !
Par exemple, la fonction int
peut lever des exceptions ValueError
et TypeError
.
Lorsqu’une exception est levée, par défaut Python quitte le programme.
Pour éviter qu’une exception ne quitte le programme, on doit capturer l’exception :
In [17]:
try:
i = int('je ne suis pas entier')
except ValueError:
i = 0
except TypeError:
i = -1
else:
print('Cool, aucune erreur !')
print(i)
Dans try
, on écrit les lignes de code à tenter d’exécuter.
En cas d’erreur, on se réfère au except
correspondant à l’erreur (ici ValueError
) et on exécute son code.
Si aucune erreur ne se produit, on exécute ce qu’il y a dans else
.
Seul try
et un except
sont obligatoires, n’utiliser else
et les except
supplémentaires que si nécessaires.
En Python, lorsque que quelque chose d’innatendu et grave se produit, on préfère lever une exception plutôt que de faire planter et arrêter le programme.
Pour cela, il faut utiliser le mot-clé raise
et choisir le type d’exception parmi la liste des exceptions disponibles. Idéalement, on ajoute un message d’erreur, mais ce n’est pas obligatoire.
Par exemple :
In [18]:
message = input('Quel âge avez-vous ? ')
if not message.isdigit():
raise TypeError('Vous devez taper un nombre')
if message == '0':
raise NotImplementedError
print('Vous avez', message, 'ans')
Pour lire un fichier, utiliser le mot-clé with
, la fonction open
et des méthodes de l’objet renvoyé :
with open('un_fichier.txt') as fichier:
contenu = fichier.read()
print(contenu)
Si le fichier n’existe pas, une exception FileNotFoundError
est levée.
Utiliser un try
…except
pour gérer cette situation.
Par défaut, open
ouvre les fichiers pour être lus, le mode d’ouverture 'r'
.
Pour avoir un comportement différent, il faut changer le mode d’ouverture.
Ainsi, pour écrire dans un nouveau fichier ou écraser un fichier existant :
with open('un_fichier.txt', 'w') as fichier:
fichier.write('Une première ligne\nEt une seconde')
Un mode spécial, 'a'
(pour “append”), permet d’ajouter du contenu à la fin du fichier :
with open('un_fichier.txt', 'a') as fichier:
fichier.write('Une troisième ligne')
Uniquement en utilisant Python, faire ce qui suit :
essai.txt
contenant le texte « Je sais écrire :D ».Exécuter un programme externe pour obtenir son code de retour :
import os
return_code = os.system('ls /home/')
⇒ Intérêt vite limité, et peu sécurisé.
Exécuter un programme externe pour obtenir sa sortie :
from subprocess import getstatusoutput
return_code, output = getstatusoutput('ls /home/')
print(return_code)
print(output)
⇒ Plus intéressant, mais peu sécurisé et toujours un peu limité.
Interagir complètement avec un programme externe :
from subprocess import Popen, PIPE
p = Popen(['ls', '/home/'], stdout=PIPE, stderr=PIPE)
p.wait()
print(p.returncode)
print(p.stdout.read().decode())
… et plein d’autres interactions.
Pour exécuter un script directement sans appeler Python :
#!/usr/bin/env python3
en première ligne du fichier (le “shebang”)chmod +x script.py
Le module argparse
inclus dans Python permet de créer des outils de qualité en ligne de commande :
from argparse import ArgumentParser
parser = ArgumentParser(description='Ce script lit ou écrit un fichier.')
parser.add_argument('chemin', help='Chemin vers le fichier')
parser.add_argument('--contenu', help='Contenu écrit dans le fichier')
args = parser.parse_args()
if args.contenu is None:
with open(args.chemin) as fichier:
print(fichier.read())
else:
with open(args.chemin, 'w') as fichier:
fichier.write(args.contenu)
Pour plus de détails, lire la documentation : docs.python.org/3/library/argparse
Depuis Python 3 ⇒ presque plus de problèmes d’encodage !
Voir Python 2 vs 3 précédemment.
Mais parfois toujours besoin de conversions.
Conversion bytes
→ str
:
b'abc'.decode() # Renvoie 'abc'
Conversion str
→ bytes
:
'abc'.encode() # Renvoie b'abc'
Ici on utilise par exemple ISO 8859-1, la norme Windows pour l’Europe universelle. C’est sans doute l’encodage autre que UTF-8 que vous rencontrerez le plus souvent.
Conversion bytes
→ str
:
'\xe9'.decode('iso-8859-1') # Renvoie 'é'
Conversion str
→ bytes
:
'é'.encode('iso-8859-1') # Renvoie b'\xe9'
Voir la liste complète des noms d’encodages gérés par Python.
pathlib
Dans des scripts, souvent besoin de lister des fichiers, découper des chemins etc.
⇒ pathlib, une solution récemment incluse à Python pour faciliter tout cela.
from pathlib import Path
usr_bin = Path('/usr/bin/')
print(usr_bin.is_dir()) # True
print(list(usr_bin.glob('python*'))) # Liste les exécutables python
print(usr_bin.parent) # /usr
home = Path.home()
projets = home / 'Projets Python'
print(projets.exists()) # Probablement False
print(Path('test').absolute()) # Transforme en chemin absolu.
print(Path('fichier.txt').name) # fichier
print(Path('fichier.txt').suffix) # .txt
print(Path('fichier.tar.gz').suffixes) # ['.tar', '.gz']
Pour plus d’informations : docs.python.org/3/library/pathlib
En utilisant exclusivement pathlib
et argparse
, écrire un script en ligne de commande nommé ls.py
permettant d’afficher le chemin de tous les fichiers Python trouvés récursivement dans le dossier actuel. Cela affichera aussi optionnellement la taille des fichiers. Si un argument est passé à ls.py
en ligne de commande, on cherche dans l’argument.
Les chemins seront affichés de manière absolue, et par ordre alphabétique. On limite le nombre de chemins affichés à 1000, modifiable par un argument.
Exemples :
./ls.py --limite 2
journal.py
ls.py
./ls.py /usr --limite 3 --afficher-taille
7261 octets /usr/lib/update-notifier/apt_check.py
4848 octets /usr/lib/update-notifier/backend_helper.py
15467 octets /usr/lib/rhythmbox/plugins/alternative-toolbar/alttoolbar_plugins.py
In [19]:
def espionner_fonction(fonction):
def nouvelle_fonction(*args, **kwargs):
print('Début de', fonction.__name__, 'arguments :', args, kwargs)
resultat = fonction(*args, **kwargs)
print('Fin de la fonction, résultat :', resultat)
return resultat
return nouvelle_fonction
@espionner_fonction
def calcul(x, y=0):
return x ** 2 + y
In [20]:
calcul(2)
Out[20]:
In [21]:
calcul(x=5, y=8)
Out[21]:
Les concepts de POO ont commencé à être formulés dans les années 1960, soit au tout début de la programmation.
Des premiers langages s’essayèrent à la POO dans les années 1960 et 1970.
Toutefois, c’est dans les années 1980 que se créent les premiers langages dont le concept d’objet est central, popularisé essentiellement par C++, la version étendue à la POO du célébrissime C.
Dans les années 1990, le concept d’objet est au cœur de tous les nouveaux langages : Python, Java, Ruby, C#, etc.
Dans ces langages des années 1990, presque tout est objet. C’est comme cela qu’en Python, nous avons pu utiliser des méthodes sur quasiment tous les types de données.
Java est un exemple célèbre de POO pour son utilisation abusive : tout programme Java définit des classes, même si c’est pour écrire le fameux « Hello World » !
En Python, nous n’avons pas encore défini de classe, car on peut très bien se passer d’en créer. Toutefois, c’est indispensable dans bien des cas.
La POO répond à un problème très concret : comprendre du code rapidement, travailler en équipe avec moins de stress, le tout en un minimum d’effort.
Le problème que résout la POO est de comprendre quelle donnée on manipule. Sans objets, on ne manipule que des listes, des dictionnaires, des entiers, du texte. Dès qu’un programme se complique, il est difficile de mémoriser qu’une variable qu’on a récupéré à l’entrée d’une fonction contient, par exemple, « une liste de dictionnaires associant du texte à une liste de nombres entiers ». C’est encore pire lorsqu’on manipule des structures récursives.
L’intérêt de la POO consiste à regrouper des données sous un nom parlant. En gros, cela revient à remplacer la description d’une variable voiture
de ceci :
Des plaques de métal jointes avec des vis fixées
sur plusieurs barres de métal soudées entre elles
autorisant la rotation d’un axe joint à deux morceaux de métal
auxquels sont adjoints des membranes de caoutchouc sous pression.
à ceci :
Une carosserie sur un châssis muni d’un essieu entraînant les roues.
Ici, carosserie
, châssis
, essieu
et roue
sont des classes qu’il faut définir. Mais quand je manipule le concept « voiture », je me fiche de connaître le détail de conception de la carosserie, du châssis, etc. J’ai besoin de manipuler une quantité raisonnable et compréhensible de concepts clairs. Si je veux connaître le détail du fonctionnement d’un châssis, je vais voir sa classe.
Il n’y a pas de règle claire sur le moment où arrêter d’utiliser des types tout faits et créer ses classes pour clarifier.
Plusieurs signes indiquent qu’il faut avoir recours à des classes :
En résumé, quand ça risque d’être compliqué, structurer avec des classes.
Dans tous les autres cas, surtout pour des scripts, utiliser des fonctions ou même du code directement tapé à la racine du programme.
Une classe :
Un objet = une instance d’une classe ou d’un type
Quand on crée un objet à partir d’une classe, on dit qu’on instancie une classe.
Éléments importants d’une classe :
In [22]:
class Stylo: # Nom de classe
encre_par_lettre = 1 # Attribut de classe
Création d’un objet / instanciation de la classe :
In [23]:
stylo = Stylo()
On va créer une classe permettant de générer du HTML.
Comme le HTML contient des règles spéciales pour chaque type de balise, on va créer au final plusieurs classes définissant les spécificités de chaque type de balise.
Pour le moment, on s’intéresse à la logique générale.
On crée donc une classe HtmlTag
contenant :
name
valant 'div'
. Dans chaque nouveau type, on changera ce nom pour être img
, span
, p
, strong
, etc.self_closing
valant False
. Cela permettra de définir si un élément HTML ressemble à <div></div>
(la plupart des cas, quand self_closing
est False
) ou <div />
(quand self_closing
est True
).mandatory_attrs
valant []
. C’est une liste d’attributs obligatoires pour un type d’élément HTML donné.
In [24]:
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
stylo.encre_par_lettre = 2
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
Mais modifier un attribut de classe donne des conséquences plus complexes :
In [25]:
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
Stylo.encre_par_lettre = 2
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
stylo.encre_par_lettre = 3
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
Stylo.encre_par_lettre = 4
print(Stylo.encre_par_lettre, stylo.encre_par_lettre)
Pourquoi stylo.encre_par_lettre
est il modifié la première fois, mais pas la 3e fois ? Parce que la première fois, l’attribut n’est pas encore défini sur l’instance, il récupère l’attribut de classe à la place.
In [26]:
class Stylo:
encre_par_lettre = 1
def ecrire(self, texte):
consommation = self.encre_par_lettre * len(texte)
print("%s écrit '%s', consommant %d d’encre"
% (self, texte, consommation))
stylo = Stylo()
stylo.ecrire('bonjour')
Améliorer HtmlTag
pour lui ajouter une méthode render_html
sans argument à part self
.
Cette méthode effectuera le rendu HTML de l’élément, sous forme de chaîne de caractères.
Cela doit donc renvoyer
<div></div>
si name
vaut 'div'
et self_closing
vaut False
<img />
si name
vaut 'img'
et self_closing
vaut True
« Spéciales » car elles ont des sens bien particuliers dans Python.
On les appelle aussi couramment « méthodes magiques ».
Elles permettent aux classes de s’intégrer dans la syntaxe Python très naturellement et ainsi d’éviter d’utiliser tout le temps des méthodes lors de l’utilisation d’une classe.
Toutes les méthodes spéciales commencent et finissent par un double underscore, __
.
Quelques méthodes spéciales importantes :
Nom de la méthode | Utilité |
---|---|
__init__ |
Instanciation de la classe |
__str__ |
Conversion de l’objet en chaîne de caractères |
__repr__ |
Représentation de l’objet |
__add__ , __sub__ , … |
Opérations arithmétiques |
__lt__ , __gt__ , __eq__ , … |
Comparaisons |
__del__ |
Suppression de l’objet (même automatique) |
Pour en savoir plus, voir la liste complète.
In [27]:
class Stylo:
nom = 'stylo'
encre_par_lettre = 1
def __init__(self, couleur):
self.couleur = couleur
print('On crée un stylo %s.' % couleur)
def __str__(self):
return self.nom
def ecrire(self, texte):
consommation = self.encre_par_lettre * len(texte)
print("%s écrit '%s', consommant %d d’encre."
% (self, texte, consommation))
stylo = Stylo('bleu')
stylo.ecrire('bonjour')
Ajouter une méthode spéciale à HtmlTag
pour que
str(HtmlTag())
renvoie
'<div></div>'
.
Ajouter une méthode spéciale à HtmlTag
de sorte que :
HtmlTag(HtmlTag(), HtmlTag())
serait<div><div></div><div></div></div>
.HtmlTag(id='container', data_url='http://python.org')
serait<div id="container" data-url="http://python.org"></div>
.Pour ce faire, on devra aussi ajouter des attributs d’instance children
et attrs
.
En cas d’absence d’un attribut obligatoire, lever une KeyError
avec un message adéquat.
Gérer le cas spécial de l’attribut class
(mot réservé en Python) en attendant à la place un argument class_name
.
Faire en sorte qu’on puisse demander le nombre d’enfants d’un élément HTML avec la fonction len
:
tag = HtmlTag(HtmlTag(), HtmlTag())
print(len(tag)) # Renvoie 2
Faire en sorte que l’on puisse facilement lire, modifier ou retirer des attributs comme ceci :
tag = HtmlTag(data_url='')
tag['id'] = 'container'
print(tag['id']) # Renvoie 'container'
del tag['id']
Modifier HtmlTag
pour qu’on puisse saisir du texte dans la liste des enfants, de sorte que
HtmlTag(HtmlTag(), 'du texte')
renvoie
<div><div></div>du texte</div>
In [28]:
import datetime
class Human:
def __init__(self, birth_year):
self.birth_year = birth_year
@property
def age(self):
return datetime.date.today().year - self.birth_year
human = Human(1989)
print(human.age)
human.age = 60
In [29]:
import datetime
class Human:
def __init__(self, birth_year):
self.birth_year = birth_year
@property
def age(self):
return datetime.date.today().year - self.birth_year
@age.setter
def age(self, new_age):
self.birth_year = datetime.date.today().year - new_age
human = Human(1989)
print(human.age)
human.age = 60
print(human.age, human.birth_year)
Dans une classe, un attribut, méthode ou propriété peut-être public ou privé.
Ce qui est public est accessible à tout le monde, et ce qui est privé n’est accessible que depuis l’intérieur de la classe, dans une méthode ou une propriété.
Dans certains langages, il existe aussi d’autres subtilités pour un attribut/méthode/propriété, comme la lecture seule (ou readonly) ou le fait d’être statique.
En Python, on définit tout est public par défaut, sauf si le nom de l’attribut/méthode/propriété commence par deux underscores __
(uniquement au début, pas à la fin).
In [30]:
class Human:
def __init__(self, birth_year):
self.__birth_year = birth_year
def get_century(self):
if self.__birth_year <= 2000:
return 'XXe'
return 'XXIe'
human = Human(1989)
print(human.get_century())
print(human.__birth_year)
Par convention, il arrive très souvent en Python qu’on fasse commencer un attribut/méthode/propriété par un seul underscore, comme def _get_internal_stuff(self):
. Ce n’est pas privé, mais cette convention indique que c’est une fonctionnalité interne qu’il est déconseillé d’utiliser ou modifier si on a un doute.
On utilise très rarement les attributs/méthodes/propriétés privés, car on considère que les développeurs sont adultes et responsables. On préfère autoriser un développeur à faire des bêtises et ne pas le bloquer plutôt que de le traiter comme un enfant turbulent. On préfère presque systématiquement le simple underscore.
Stylo
class Stylo:
encre_par_lettre = 1
def __init__(self, couleur='noir'):
self.couleur = couleur
self.remplir()
def remplir(self):
self.__quantite_encre = 40
@property
def est_vide(self):
return self.__quantite_encre <= 0
def ecrire(self, texte):
self.__quantite_encre -= len(texte) * self.encre_par_lettre
if self.est_vide:
raise ValueError('Le stylo est vide.')
print(texte)
Maintenant on peut produire des stylos et s’en servir :
stylo = Stylo('rouge') # Un stylo rouge
stylo.ecrire('quelque chose')
stylo.ecrire('blabla' * 5) # Le stylo est vide.
stylo.remplir() # Remet de l’encre
stylo.ecrire('blabla' * 5) # Il marche à nouveau !
Hériter d’une classe permet de réutiliser son code, tout en le personnalisant. Ici, on créé une sous-classe Crayon
héritant de Stylo
:
class Crayon(Stylo):
encre_par_lettre = 0.5
crayon = Crayon() # Un crayon noir
crayon.ecrire('quelque chose')
crayon.ecrire('blabla' * 5)
crayon.ecrire('blabla' * 5)
crayon.ecrire('blabla' * 5) # Le stylo est vide.
On peut même écraser des méthodes, éventuellement en réutilisant leur fonctionnement de base.
class Feutre(Stylo):
def remplir(self):
self.quantite_encre = 60
def ecrire(self, texte):
try:
super().ecrire(texte) # Exécute la méthode écrasée
except ValueError:
raise ValueError('Le feutre est vide.')
Créer une myriade de sous-classes à HtmlTag
pour gérer des éléments HTML communs. Implémenter au moins les sous-classes :
P
Strong
Em
Span
Div
Img
(attributs src
et alt
obligatoires, self-closing)Créer ensuite des instances de ces sous-classes de sorte que le rendu HTML obtenu en utilisant str
sur une des instances soit :
<div class="container">
<p>
<em>Python</em> est un
<span title="Pas si compliqué">langage <strong>multi-paradigme</strong></span>.
<img src="https://www.python.org/static/img/python-logo.png" alt="Python logo" />
</p>
</div>
Attention, j’ai ajouté de l’indentation au HTML pour la lisibilité, votre code généré ne doit pas faire ces ajouts, il doit être en une ligne, un peu tout collé.
Créer une classe Vehicule contenant :
vitesse_max
en km/h, valant la vitesse de la lumièreconsommation
, la quantité de carburant consommée pour 100 km, valant 10
reservoir_max
définissant la taille de la réserve de carburant, valant 1000
reservoir
, le remplissage du réservoir, plein par défautfaire_le_plein
remplissant le réservoirEmpêcher le véhicule de rouler si il n’a plus assez d’essence pour parcourir la distance demandée.
Créer deux classes Voiture
et Avion
héritant de Vehicule
, avec des vitesses maximales de 160
et 950
, des consommations de 6
et 1500
et des réservoirs de 50
et 260000
.
En utilisant ces classes, trouver approximativement en tâtonnant la distance maximale que peut faire une voiture et un avion, et en combien de temps minimum.
Créer deux classes C3
et Zoe2017
héritant de Voiture
, avec des vitesses maximales de 150
et 155
, des consommations de 6
et 13
et des réservoirs de 40
et 41
.
Trouver de la même manière à tâton les distances maximales et durées de voyages.
Reprendre la classe Vehicule
des exercices précédents, et y ajouter un attribut de classe nom
valant 'Véhicule'
.
Écraser cet attribut de classe dans toutes ses sous-classes, par exemple 'Avion'
pour Avion
ou 'Zoé 2017'
pour Zoe2017
.
Ajouter une méthode spéciale à Vehicule
de sorte que str(Voiture())
affiche « Voiture », str(Zoe2017())
affiche « Zoé 2017 », etc.
Ajouter une méthode spéciale pour ajouter un peu de carburant à un véhicule comme ceci :
c3 = C3()
c3.parcourir(200)
print(c3.reservoir) # 28.0
c3 += 5
print(c3.reservoir) # 33.0
Ajouter une méthode spéciale qui affiche par exemple « C3 part à la casse ! » quand on supprime un objet. En Python, les objets se suppriment automatiquement, mais on peut forcer la suppression en faisant :
c3 = C3()
del c3
In [31]:
class Book:
max_pages = 100000
size = 'any'
class Novel(Book):
max_pages = 2000
size = 'pocket'
class ScienceReport(Book):
max_pages = 500
size = 'A4'
class ScienceNovel(ScienceReport, Novel):
pass
book1 = Novel()
book2 = ScienceNovel()
print(isinstance(book1, Novel),
isinstance(book1, Book),
isinstance(book1, ScienceReport))
print(isinstance(book2, Novel),
isinstance(book2, Book),
isinstance(book2, ScienceReport))
La Programmation Orientée Objet existe dans la plupart des langages modernes. Les concepts vus restent les mêmes, mais la syntaxe change, naturellement.
Quelques concepts sont souvent absents :
Pour une comparaison en détail, voir l’article Wikipedia comparant la POO) à travers les langages.
class Stylo:
encre_par_lettre = 1
def __init__(self, couleur='noir'):
self.couleur = couleur
self.remplir()
def remplir(self):
self.__quantite_encre = 40
@property
def est_vide(self):
return self.__quantite_encre <= 0
def ecrire(self, texte):
self.__quantite_encre -= len(texte) * self.encre_par_lettre
if self.est_vide:
raise ValueError('Le stylo est vide.')
print(texte)
stylo = Stylo('rouge') # Un stylo rouge
stylo.ecrire('quelque chose')
stylo.ecrire('blabla' * 5) # Le stylo est vide.
stylo.remplir() # Remet de l’encre
stylo.ecrire('blabla' * 5) # Il marche à nouveau !
public class Stylo {
public int encreParLettre = 1;
public String couleur = "noir";
private int quantiteEncre;
public Stylo() {
this.remplir();
}
public Stylo(String couleur) {
this.couleur = couleur;
this.remplir();
}
public void remplir() {
this.quantiteEncre = 40;
}
public boolean getEstVide() {
return this.quantiteEncre <= 0;
}
public void ecrire(String texte) throws IllegalArgumentException {
this.quantiteEncre -= texte.length() * this.encreParLettre;
if (this.getEstVide()) {
throw new IllegalArgumentException("Le stylo est vide.");
}
System.out.println(texte);
}
}
public class UtiliseStylo {
public static void main(String[] args) {
Stylo stylo = new Stylo("rouge");
stylo.ecrire("quelque chose");
String texte = String.format("%0" + 5 + "d", 0).replace("0", "blabla");
stylo.ecrire(texte);
stylo.remplir();
stylo.ecrire(texte);
}
}
#include <string>
#include <iostream>
#include <stdexcept>
using namespace std;
class Stylo {
public:
int encre_par_lettre = 1;
string couleur;
Stylo();
Stylo(string couleur);
void remplir();
bool get_est_vide();
void ecrire(string texte);
private:
int quantite_encre;
};
Stylo::Stylo() : couleur("noir") {
this->remplir();
}
Stylo::Stylo(string couleur) : couleur(couleur) {
this->remplir();
}
void Stylo::remplir() {
this->quantite_encre = 40;
}
bool Stylo::get_est_vide() {
return this->quantite_encre <= 0;
}
void Stylo::ecrire(string texte) {
this->quantite_encre -= texte.length() * this->encre_par_lettre;
if (this->get_est_vide()) {
throw std::invalid_argument("Le stylo est vide.");
}
std::cout << texte << std::endl;
}
int main() {
Stylo stylo = Stylo("rouge");
stylo.ecrire("quelque chose");
string texte = "";
for (int i = 0; i < 5; i++) {
texte += "blabla";
}
stylo.ecrire(texte);
stylo.remplir();
stylo.ecrire(texte);
}
Une expression régulière permet de reconnaître un motif dans une chaîne de caractères et éventuellement d’extraire une partie de cette chaîne de caractéristiques.
Trouver si une chaîne correspond à un motif :
import re
match = re.match(r'^Mon nom est .+$', 'Mon nom est Bertrand Bordage')
Si match
est None
, alors le texte ne correspond pas au motif.
Sinon, match
est un objet permettant d’extraire des groupes de caractères. Pour définir des groupes :
import re
match = re.match(r'^Mon nom est (.+)$', 'Mon nom est Bertrand Bordage')
print(match.group(1)) # Affiche « Bertrand Bordage »
De nombreux moyens de préciser des motifs, tous listés sur la documentation du module re
.
Notation | Traduction | Notation | Traduction |
---|---|---|---|
. |
N’importe quel caractère | ? |
Répète une expression 0 ou 1 fois |
\w |
N’importe quel lettre | * |
Répète une expression 0 ou plus de fois |
\d |
N’importe quel chiffre | + |
Répète une expression 1 ou plus de fois |
[] |
N’importe lequel des caractères entre crochets | {2,5} |
Répète une expression 2 à 5 fois |
On va écrire un script simulant une discussion banale.
À tout moment, l’utilisateur peut écrire quelque chose d’innatendu, le script ne doit pas planter.
Il doit afficher à la place « Désolé, je n’ai pas compris. » puis poser à nouveau sa question.
Écrire un script demandant à l’utilisateur « Nom et ville ? », l’utilisateur devra répondre par exemple :
« Je m’appelle Yves et j’habite Yvetôt » ou « Je m’appelle Antonio et j’habite Venise ».
Répondre à l’utilisateur :
« Bonjour Yves ! » ou « Bonjour Antonio ! »
Puis lui demander : « Quel temps fait-il à Yvetôt ? » ou « Quel temps fait-il à Venise ? »
L’utilisateur devra répondre par exemple :
« Nuageux, avec une température de 9 °C » ou « Ensoleillé, avec une température de 27 °C »
Récupérer la température, puis afficher :
Afficher « Bon, je dois vous laisser, passez une bonne journée ! »
Nous allons utiliser requests et BeautifulSoup 4 pour récupérer une page web et l’analyser. Installation :
pip install beautifulsoup4 requests
Ici, nous allons voir comment :
In [32]:
from bs4 import BeautifulSoup
import requests
account = 'cesi_alternance'
# Requête HTTP téléchargeant la page du compte Twitter
reponse = requests.get('https://twitter.com/' + account)
# Création d’un objet BeautifulSoup pour analyser le HTML
soup = BeautifulSoup(reponse.text, 'html.parser')
# On utilise un sélecteur CSS pour récupérer
# la balise contenant le nombre d’abonnés
followers_css_selector = '.ProfileNav-item--followers .ProfileNav-value'
followers_tag = soup.select(followers_css_selector)[0]
# Récupère la valeur de l’attribut HTML data-count de la balise
followers = followers_tag['data-count']
print('@' + account, 'a', followers, 'abonnés.')
La programmation asynchrone sert à exécuter plusieurs tâches simultanément.
Utile pour :
Dans Python, plusieurs modules pour la programmation asynchrone : threading
, multiprocessing
, concurrent
Malheureusement, ils sont complexes à utiliser :
Récemment, une nouvelle manière de faire de la programmation asynchrone en Python :
le module asyncio
et les mots-clés async
et await
.
Révolutionnaires, mais cela manque de maturité, cela changera encore beaucoup à l’avenir et il y a encore de quelques bugs.
⇒ Il vaut mieux attendre encore un peu !
Créer un petit jeu avec des créatures affrontant un humain (un peu comme Pokémon par exemple). Les humains et créatures ont quelques capacités classiques des RPG :
On gère trois actions pour commencer :
Certaines données non affichées sont presque indispensables :
Il est très fortement recommandé de créer une classe, par exemple Personnage
stockant les données et gérant la logique des personnages. Ainsi, chaque nouveau type de personnage sera une sous-classe ajustant les paramètres.
Pour les plus téméraires, vous pouvez ajouter de nombreux systèmes usuels, comme les coups critiques, la fuite d’un combat, l’armure, différents types d’attaque, etc.