Python pour les débutants¶
Merci à Benjamin et à Louis pour leur aide active.
Liste des outils utilisés pour réalister cette page et cette présentation:
- Markdown
- MkDocs
- landslide
- git
- Jenkins
- nano/vim/vscode/gedit ...
- Ubuntu
Python ?¶
C'est quoi ?¶
Python est un langage informatique (infolangage) à la fois très simple et très complet. Il permet de très facilement se mettre à la programmation, son code est facilement lisible, mais en même temps, il est utilisé dans l'industrie au sens large (machines outils, jeux vidéo, infographie, cinéma. Il est également au cœur de certains progiciels comme Blender. Il est tellement complet qu'il est au cœur du "big data"; il est utilisé massivement par les "data scientists".
Vous l'aurez compris, Python peut tout autant s'adresser à des débutants qu'à des informaticiens purs et durs. La preuve : Python est privilégié pour apprendre la programmation sur Raspberry Pi et ce dès 8 ans à peine.
Quelle version de Python dois-je installer ?¶
Python, comme beaucoup de choses en informatique (et comme les pokemons) évolue. À l'heure actuelle on en est à la version 3.9.1.
MAIS, la version 2.X n'est pas (encore) morte, même si elle n'est plus supporté officiellement par le consorcium Python. Suivant le domaine d'application, il est même courant de voir Python 2.x utilisé au lieu de Python 3.x pour cause de compatibilité (code source ou module externe). Cependant, de plus en plus d'organisations sont passés à Python 3, et il est plus que temps de passer à Python 3 dorénavant. Chez Emerson (ex PDGM) nous utilisions Python 2.7 à cause de notre historique, mais récement nous sommes nous aussi passés à Python 3, et cette formation sera donc basée sur Python 3 (3.9).
Cette formation étant 100% compatible avec une Raspberry Pi, si vous voulez en utiliser une, vous pourrez "pourrir" sa configuration sans avoir peur des conséquences, un reformatage de carte SD et hop on est de nouveau OK... avis aux entendeurs...
Installons Python¶
Linux¶
Sous Linux, rien de plus simple, Python est très souvent déjà installé car un nombre non négligeable de scripts, et d'applications sont en Python. Cependant, la migration vers Python 3 est déjà bien avancée, et avec Ubuntu 18.04 Python 2 n'est pas installé par défaut. Si Python 3 n'est pas installé, il y a 99.99% de chance que votre gestionnaire de paquets le connaisse, et il suffit donc de faire (pour Debian & Al) :
$ sudo apt install python3
Windows¶
- Aller sur le site officiel Python
- Cliquer sur "download"
- Chercher la dernière version de 3.X (3.9.1)
- Choisir le MSI 64 bits (pour des problèmes de compatibilité avec certain modules la version 32 bits peut aussi être envisagée)
- L’exécuter, next, next, next, next...
- Choisir l'ajout dans le PATH pour tous les utilisateurs
- Ajouter Python dans le
PATH(si non choisi dans les options d'installation):- Raccourcis : [Win] (la touche windows du clavier) + [Pause]
- Avancé
- Variables d’environnement
- Ajouter
C:\Python39\dans lePATHs'il n'y est pas déjà
- Voila. (Linux c'est compliqué qu'ils disent ;) )
Où se renseigner sur Python ?¶
Tout d'abord sur le site officiel de Python Il y a là des tutoriels, des exemples, mais aussi toute la documentation du langage.
Google : GIYF ! - et oui avec Python, il y a de très grandes chances que quelqu'un ait déjà fait ce que vous essayez de faire, et le plus souvent, un copier coller suffit à arriver à vos fins.
TODO: add more links
Pour s'entraîner en s'amusant :
- HackerRank
- CodinGame
- W3Schools
Un site sur des bonnes pratiques Python.
Votre humble serviteur ;)
Bonjour, monde!¶
Les informaticiens sont tous très polis. Ils commencent toujours par dire bonjour (ça ne dure jamais très longtemps, hein).
Nous allons donc faire pareil, qu'en dites-vous ? Pour cela, nous allons ouvrir une invite de commandes (terminal).
Pour Linux, vous devez bien déjà savoir non ?
Pour Windows :
- Un appui sur [Win]
- Taper :
cmd - Valider avec [Enter]
On en est donc tous à se demander comment "lancer" Python. C'est très simple :
$ python
Du coup quelque chose un peu comme cela a dû apparaître dans l'invite de commandes :
$ python
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Cela veut dire plusieurs choses :
- Python est bien installé et capable de fonctionner
- L'invite de commandes a changé et s'est mis "en mode Python" (les trois signes
>, c'est l'invite de commandes Python par défaut) - Nous allons donc pouvoir taper nos premières commandes !
C'est parti, tapez :
>>> print("Hello, world!")
Vous devriez avoir quelque chose comme cela à l'écran maintenant :
>>> print("Hello, world!")
Hello, world !
Voila, vous savez coder en Python. Le sentiment du devoir accompli ; je peux vous dire au revoir !
Non, ça ne vous suffit pas ? ... Comme disait Léo Getz dans l'arme fatale "OK OK !"
Bon, ce que nous venons de faire demande un peu d'explications.
Tout d'abord, nous avons utilisé un mot-clé du langage Python print le but de ce mot-clé est de dire à Python que nous voulons inscrire quelque chose dans le terminal. Python va donc "écrire" ce que nous avons écrit après print.
Comme pour beaucoup de langages, les doubles-guillemets (double-quotes) : "" servent à écrire du texte. Par exemple "Hello, world!" dit à Python que Hello, world ! est du texte.
Si on reprend depuis le début : print("Hello, world!") dit à Python d'écrire le texte Hello, world ! dans le terminal; ce qu'il a fait.
Pour quitter l'invite de commande il suffit de taper la commande quit()
>>> quit()
$
ipython¶
Il est à noter que l'interpréteur Python est assez spartiate et assez avare en fonctionnalités, même si la version 3 a fait des progrés.
Il pourra facilement être replacé par l'interpréteur iPython3 (codé en Python) qui est disponible via apt install ipython3 sous linux et sous widnows en suivant ce lien.
Parmi les fonctionnalités mises à disposition par iPython on pourra citer :
- Complétion
- Historique des commandes utilisées (y compris lors de précédentes sessions)
- Affichage des valeurs plus agréable
- ...
Les Pythons aiment les maths¶
Et oui, qui dit ordinateur ou informatique dit maths. Et bien Python sait faire la calculatrice avancée :
>>> 1+1
2
>>> ( 1 + 2 * 12 ) // 3
8
Note
Le signe // retourne le résultat de la division euclidienne.
Il sait aussi jongler avec les nombres imaginaires (en anglais, i se note j) :
>>> (1+3j)**2
(-8+6j)
Par contre, il ne semble pas connaître la trigonométrie :
>>> sinus(3.14159)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sinus' is not defined
Ceci est intéressant à plusieurs titres :
- On ne peut pas (encore) demander à Python de faire nos exercices de géométrie,
- On voit ce qu'il se passe quand Python n'est pas content :
- Il nous donne le nom du fichier qu'on exécute (ici
<stdin>), - Il nous donne la ligne où il y a un problème (ici la ligne 1),
- Il nous dit même ce qui ne va pas :
sinusest inconnu pour Python, il n'est pas défini.
- Il nous donne le nom du fichier qu'on exécute (ici
Mais une minute, on nous parle de nom de fichier, de scripts Python, etc. Comment ça marche ?
On va scripter !¶
Si nous fonctionnions toujours avec l'invite de commande Python, nous serions obligés de réécrire toujours nos commandes Python et cela ne serait pas très efficace.
Un script c'est un fichier qu'un programmeur (vous) écrit et que l'on demande à Python d’exécuter. C'est un ensemble de commandes, identique à celui que l'on pourrait écrire dans le terminal.
C'est d'ailleurs ce que nous allons faire avec nos premières commandes (print et maths).
Je laisse le choix de l’éditeur (IDE) au lecteur, personnellement, j'utilise vim, nano, gedit, atom, VSCode, KDevelop, tout dépend de mon humeur.
Nous allons créer un nouveau fichier hello.py, et pour que l'on soit tous au même niveau, je vous conseille de le mettre dans une arborescence telle que celle-ci :
Training_Python/
└── 1_first_script
└── hello.py
Dans ce fichier nous allons copier le texte suivant :
print("Hello, world!")
Sauvegardons le, et voyons comment dire à Python d’exécuter ce script. Comme vous vous en doutez, c'est très complique. Dans un nouveau terminal, il suffit de faire :
$ python Training_Python/1_first_script/hello.py
Hello, world!
Comme on peut le voir, notre commande Python s'est bien exécutée.
Maintenant, créons un fichier maths.py avec le contenu suivant :
1+1
( 1 + 2 * 12 ) // 3
(1+3j)**2
sinus(3.14159)
Demandons à Python de l’exécuter comme tout à l'heure :
$ python Training_Python/1_first_script/maths.py
Traceback (most recent call last):
File "Training_Python/1_first_script/maths.py", line 4, in <module>
sinus(3.14159)
NameError: name 'sinus' is not defined
Rien ne va plus... Que c'est-il passé ?
En 5 mots : ce que nous avons demandé !
Et oui un ordinateur (et un langage informatique aussi) est bête et discipliné.
Nous avons demandé à Python de faire des maths, et il l'a fait. Il a effectivement calculé 1+1, puis les différentes formules qu'on lui a demandé. Jusqu'à la ligne avec sinus, qui une fois encore a fait une erreur.
Cette fois-ci on peut remarquer que le nom du fichier où l’erreur s'est produite est donné, ainsi que le numéro de ligne (ligne 4 dans maths.py). Python nous recopie même la ligne pour "voir" où se trouve l’erreur.
OK, il nous donne l’erreur, mais où sont nos calculs ??? À votre avis ?
...
Et bien il manque quelque chose : print.
Contrairement au mode interactif, où Python écrit le résultat automatiquement dans le terminal, avec un script, il faut dire à Python d'écrire (imprimer) le résultat.
Ré-essayons avec ce contenu maintenant dans le fichier maths2.py
print(1+1)
print(( 1 + 2 * 12 ) // 3)
print((1+3j)**2)
Ce qui donne :
$ python Training_Python/1_first_script/maths2.py
2
8
(-8+6j)
YES, c'est bon cette fois !
Le ZEN du Python¶
Python est sans cesse amélioré, nous l'avons déjà dit. Les améliorations du langage passent par des PEP Python Extension Proposals. Ces PEPs sont acceptés ou non par la communauté, et finissent ou non dans les versions publiques de Python.
Très tôt dans le développement de Python, il y a eu des propositions visant à rendre le langage un peu particulier par rapport à nombre d'autres langages PEP8 & PEP20.
Le premier, PEP8, concerne le formatage du code. C'est assez classique, mais la lecture de ce PEP est une bonne idée pour qui veut faire du Python. Tout fichier inclus dans Python doit suivre ces conventions de codage. De même, toute correction proposée pour aider au développement de Python doit aussi suivre ces règles. Il y a des IDEs (atom, VSCode) qui proposent des extensions afin de vérifier que le code est bien compatible avec PEP8.
Le second, PEP20, est encore plus intéressante à lire. Il donne des règles de bonne conduite lorsque l'on écrit du code :
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
...
Readability counts.
...
Pour voir l’intégralité du PEP20, dans l'invite de commandes Python, tapez ceci :
>>> import this
Beautiful is better than ugly.
...
Et oui, en Python, la lecture du code est importante, et il est préférable de faire simple plutôt que complexe, etc. C'est en partie pour cela que le code Python est facile à lire, même pour un enfant de 8 ans.
Commentaires¶
Comme nous venons de le voir, la lisibilité est importante, et pour rendre du code plus lisible on put utiliser des phrases d'explication qui ne seront pas exécutées par Python : les commentaires.
En Python, pour écrire un commentaire, il suffit d'écrire # puis votre commentaire, comme cela :
# compute 1+1 ?
print(1+1)
Un commentaire n'a pas besoin d'être en début de ligne :
print(1+1) # expected result : 2
Types de données (1/2)¶
Comme je l'ai déjà dit, Python est un langage simple, mais complet. En effet, la lecture du code est importante comme on l'a vu (Python zen), mais les types de données que peut manipuler (facilement) Python sont énormes.
Les entiers : int¶
Comme on l'a vu recentrement, on peut manipuler des entiers :
>>> 3*5
15
Les réels : float¶
On peut aussi manipuler des nombres réels :
>>> 3.14159*2
6.28318
Les nombres imaginaires¶
Et oui, on l'a déjà vu aussi
>>> (3+2j)**3
(-9+46j)
Les très grands nombres¶
Contrairement à beaucoup de langages, il n'y a pas besoin, en Python, de dire que l'on veut manipuler des grands nombres, Python adapte tout seul :
>>> 10*9*8*7*6*5*4*3*2*1*100000000
362880000000000
Les textes¶
On l'a déjà vu, un texte est un ensemble de lettres qui sont placées entre des double quotes.
>>> "Hello!"
'Hello!'
Et bien, en Python on peut aussi le placer entre simple quote cela n'a pas d'importance.
>>> 'Hello!'
'Hello!'
Et pour taper des textes sur plusieurs lignes on peut aussi utiliser les triples simple quotes, ou les triples double quotes. Cela est très utile quand on fait un script; mais beaucoup moins lors qu'on utilise la ligne de commande interactive.
>>> """Hello
... world"""
'Hello\nworld'
Note
L'invite de commandes Python mets trois petits points lorsque la commande est sur plusieurs lignes.
Note
Dans la majeure partie des langages de programmation, \n signifie "saut à la ligne".
Les variables¶
Utiliser Python pour simplement faire des calculs c'est un peu comme ne pas passer la seconde vitesse dans une voiture. On peut faire beaucoup mieux.
La notion mathématique de variable est la suivante (Wikipédia) :
Dans les mathématiques élémentaires, une variable est une grandeur dont la valeur est (provisoirement) indéterminée, mais sur laquelle est effectuée une combinaison d'opérations avec soit des constantes, soit d'autres variables. Une variable n'est pas totalement précisée, sa valeur peut même être inconnue...
Les variables en informatique ne sont pas tout à fait identique. On peut plutôt voir cela comme une "boîte" sur laquelle on met une étiquette. Sur les calculatrices, il y a souvent 2 variables : M+ et M-. Ce sont des boites dans lesquelles on peut ranger des nombres pour ensuite les réutiliser. En Python c'est sensiblement pareil, sauf que les boîtes ont une étiquette, un nom, et que pour utiliser ce qui ce trouve dans la boite on peut réutiliser l'étiquette.
Par exemple, on peut facilement se dire que taper 3.14159 à chaque fois que l'on veut utiliser PI, c'est assez lassant. Pourquoi ne pas utiliser une variable et mettre 3.14159 dedans ? Voyons cela :
>>> pi = 3.14159
>>> print(pi)
3.14159
>>> pi*2
6.28318
Nous avons mis la valeurs 3.14159 dans la boite avec l'étiquette pi.
On dit plutôt que nous avons crée une variable pi à laquelle nous avons affecté la valeur 3.14159.
Nous avons ensuite utilisé cette valeur pour faire des calculs.
C'est un peu la base de la programmation, mettre des valeurs en mémoire pour ensuite les utiliser.
Quelques règles :
- une variable peut contenir des lettres, des chiffres et "_"
- une variable peut avoir des majuscules
- une variable peut avoir un nom de la taille que l'on souhaite
- une variable ne peut commencer par un chiffre
- une variable doit avoir un nom qui reflète son contenu (vous vous souvenez du zen ? Readability counts)
Il est important de remarquer qu'en Python, une variable n'est pas figée, et aussi bizarre que ça paraisse, on peut changer le type de donnée stocké dans une variable :
>>> pi = 3.14159
>>> pi
3.14159
>>> pi = "Hi"
>>> pi
'Hi'
pi est tour à tour un nombre réel, puis un texte.
Bien sûr, cet exemple est très mauvais car le code qui suivrait en devient illisible : une variable qui s'appelle PI ne devrait pas contenir autre chose que PI, surtout pas ce texte.
Types de données (2/2)¶
Maintenant que nous avons des variables, nous pouvons stocker des données en mémoire, mais comment stocker des données en grand nombre ? Utiliser des variables comme a1, a2, a3, a4, etc. ? Comment stocker alors des milliers de valeurs ?
Les listes : list()¶
Sans aller jusque là, comment allons nous stocker des notes pour des élèves afin de calculer une moyenne ? Une variable par élève avec son prénom, ou son nom ? Non, Python a une structure pour stocker ce genre de données : les listes.
Pour créer une liste il suffit de taper ce code :
>>> my_first_list = list()
>>> print(my_first_list)
[]
Jusque là, rien d'extraordinaire, mais on n'a pas dit quelle taille devait faire cette liste. Et oui, en Python une liste peut faire (presque) la taille que l'on veut, mais pour l'instant elle est vide. Pour la remplir il suffit d'appeler append() sur cette liste :
>>> my_first_list.append(1)
>>> my_first_list
[1]
>>> my_first_list.append(2)
>>> my_first_list.append(3)
>>> my_first_list.append(4)
>>> my_first_list
[1, 2, 3, 4]
Écrire append() pour chaque élément de la liste n'est pas très aisé, mais aussi pas très "lisible", ni simple. On peut donc aussi initialiser une liste avec ses éléments en écrivant :
>>> a_second_list = [1,2,3,4]
>>> a_second_list
[1, 2, 3, 4]
C'est tout de suite plus simple.
On peut aussi mélanger les types dans une liste :
>>> misc_list = [1.0, "a", [1,2,3]]
>>> misc_list
[1.0, 'a', [1,2,3]]
On peut facilement accéder à un élément donné, connaissant son ordre dans la liste, pour cela on utilise les crochets :
>>> misc_list[1]
'a'
>>> misc_list[0]
1.0
-1 permet de récupérer le dernier élément d'une liste; -2 l'avant dernier...
>>> misc_list[-1]
[1,2,3]
>>> misc_list[-2]
'a'
Et oui, en informatique tout commence à 0; donc le zeroième élément est en fait le premier en langage courant.
On peut aussi changer un élément :
>>> l = [1, 2, 3]
>>> l[0] = 5
>>> l
[5, 2, 3]
On peut connaître la taille d'une liste en utilisant la fonction pré-définie len() :
>>> len(misc_list)
3
>>> misc_list.append(2)
>>> len(misc_list)
4
On peut aussi connaître le maximum ou le minimum d'une liste (il faut cependant que la liste soit triable) :
>>> min(my_first_list)
1
>>> max(my_first_list)
4
On peut connaître la somme des éléments d'une liste (il faut une liste constituée que de nombres donc) :
>>> sum([1, 2, 3])
6
On peut trier une liste :
>>> sorted([2,3,1,4])
[1, 2, 3, 4]
On peut enlever un élément de la liste :
>>> misc_list.pop(0)
1.0
>>> misc_list
['a', [1, 2, 3], 2]
>>> misc_list.pop()
2
>>> misc_list.pop()
[1, 2, 3]
>>> misc_list.pop()
'a'
>>> len(misc_list)
0
Exercice¶
Une classe de 10 élèves a fait un contrôle, les notes sont les suivantes :
9 11 19 3 13.5 12 7 5 15 16
Donner la note minimum, maximum et la moyenne de la classe.
(Réponses : 3 19 11.05)
La liste range()¶
Il existe une liste en Python un peu spéciale : range()
Cette liste est constituée des entiers compris entre 0 et n-1 lorsque l'on appelle range(n).
range(3) est donc équivalent à [0, 1, 2]
Cette liste est très pratique pour les boucles que nous verrons plus tard.
Les tuples : tuple()¶
Les tuples sont une sorte de liste, mais dont le contenu est figé : on ne peut pas ajouter de nouvel élément et on ne peut pas changer un élément.
Les tuples sont utiles pour des questions de performance et de place mémoire.
Pour créer un tuple on fait comme pour une liste mais on échange [] par () :
>>> t = (1,2,3)
>>> t
(1, 2, 3)
On peut aussi créer un tuple à partir d'une liste :
>>> t = tuple([1,2,3])
>>> t
(1, 2, 3)
Excercice¶
Comment échanger le contenu de deux variable ?
(Réponse : a,b = b,a)
Les sets : set()¶
Les sets sont comme des listes, mais ils ont 2 grosses différences :
- Ils ne sont pas ordonnés (l'ordre de création n'est pas conservé),
- On ne peut pas avoir plusieurs fois le même élément dans un set
Ce deuxième point est très important, et est la principale raison d'être des sets. Imaginons que vous ayez une liste mais que vous ne vouliez que des éléments uniques à l'intérieur, vous passerez par un set :
>>> uniq_set_of_values = set([1, 2, 1, 3, 1, 4, 2])
>>> uniq_set_of_values
set([1, 2, 3, 4])
On peut aussi ajouter des éléments dans un set, en enlever, connaître sa taille :
>>> uniq_set_of_values.add(1)
>>> len(uniq_set_of_values)
4
>>> uniq_set_of_values.add(5)
>>> len(uniq_set_of_values)
5
>>> uniq_set_of_values.remove(5)
>>> uniq_set_of_values
set([1, 2, 3, 4])
Les dictionnaires : dict()¶
Notés dict en Python, les dictionnaires permettent de faire correspondre une clé à une valeur dans une table.
Si nous reprenons notre exemple des notes dans une classe, on peut faire correspondre à chaque élève sa note lors d'un contrôle.
Par exemple :
>>> marks = {
"toto": 0,
"riri": 12,
"fifi": 14,
"loulou": 20
}
On peut connaître la note d'un élève en demandant la valeur dans la table qui correspond à son prénom :
>>> marks["toto"]
0
>>> marks["loulou"]
20
On peut demander la taille d'un dictionnaire, comme pour les autres types en passant par len() :
>>> len(marks)
4
On peut changer une valeurs affecté à une clé (existante ou non) :
>>> marks["fabien"] = 10
>>> marks["toto"] = 2
Et oui, toto avait quand même mis son nom sur la copie.
On peut supprimer une entrée dans la table avec le mot-clé del :
>>> del marks["fabien"]
>>> len(marks)
4
Deux petites fonctionnalités intéressantes des dictionnaires : la possibilité d'avoir la liste de clés et la liste des valeurs.
>>> marks.keys()
['riri', 'fifi', 'toto', 'loulou']
>>> marks.values()
[12, 14, 2, 20]
Généralités¶
Les types que je vous ai présentés sont très puissants et permettent de représenter beaucoup de données.
Il existe cependant d'autres type de données. Pour les personnes intéressées, il est possible de regarder la documentation de NumPy ainsi que de pandas.
Je n'ai pas décrit toutes les possibilités d'action sur les types, pour plus de détails, se référer à docs.python.org, ou bien jouez sur HackerRank.
Introspection¶
L'introspection c'est le fait que l'on puisse avoir des informations sur des objets dans le langage même.
En Python, cela passe par plusieurs fonctions que l'on va voir de suite : help(), dir() et hasattr().
help()¶
help() permet d'avoir accès à l'aide d'un objet. Si on est dans un script, cela donne le "texte" de l'aide, telle qu'on peut la voir sur docs.python.org, il faudra donc passer par print() pour voir le texte.
Si on est dans un invite de commande interactif, là on accède à la documentation de manière... interactive.
>>> help(set)
Help on class set in module __builtin__:
class set(object)
| set() -> new empty set object
| set(iterable) -> new set object
...
type()¶
En utilisant type(), on peut connaître le type d'une variable ou d'un objet.
>>> d = dict()
>>> type(d)
<type 'dict'>
>>> type(3.14159)
<type 'float'>
dir()¶
dir() permet d'avoir la liste de ce que propose un objet en Python. À l'heure actuelle, on ne va pas pouvoir en faire grand chose, mais par la suite, vous verrez que c'est vraiment très puissant et permet d'avoir plein d'informations lorsque l'on écrit un script.
Un petit exemple :
>>> dir(dict)
[...
'keys',
'values',
...]
Comme vous pouvez le voir, dans un dictionnaire, il y a keys et values comme nous avons vu précédemment.
hasattr()¶
hasattr() permet de savoir si un objet détient un attribut. L'exemple étant plus parlant qu'un long discours :
>>> hasattr(dict, 'keys')
True
>>> hasattr(dict, 'val')
False
Comme on peut le voir, un dictionnaire a keys (pour obtenir la liste des clés), mais ne connaît pas val. Et pour cause, c'est values qu'il faut utiliser pour avoir la liste des valeurs dans la table.
Contrôle de flot d'exécution¶
Pour l'instant, nous avons vu comment taper des commandes les unes après les autres. En gros, on ne peut faire qu'une suite de commandes bien définie et ne jamais sortir des clous.
Mais en informatique on ne fait pas que cela, une des premières choses que l'on a envie de faire c'est d'exécuter un bloc de code que si une condition est vraie, par exemple, calculer 1 / x que si x est différent de 0.
Les bloc de code en Python¶
Généralités¶
Qu'est ce qu'un bloc de code ? Comme son nom l'indique, c'est un ensemble de lignes de codes que l'on veut exécuter "d'un bloc".
Dans la plupart des langages informatiques, un bloc de code est délimité par un indicateur (un caractère) de début et un indicateur de fin (un autre caractère). Par exemple en C++ on aura :
{CODE_BLOCK}
Ceci étant assez peu lisible, on utilise souvent l'indentation afin de rendre le code plus clair :
{
CODE_BLOCK
}
L'indentation, c'est simplement le fait d'aligner les instructions d'un même bloc de code sur la même colonne, en les précédant du même nombre d'espaces ou de tabulations.
Ceci fait souvent partie des bonnes pratiques, et donc libre aux gens de ne pas le faire.
Cas particulier de Python¶
En Python par contre, pour faire un bloc de code, il n'y a pas de séparateur, il faut indenter. Et oui, vous vous souvenez du Zen Python : la lisibilité, ça compte.
Pour qu'une ligne de code fasse partie du même bloc, il lui faut donc la même indentation que la ligne précédente :
BLOCK_1
BLOCK_2
Si on remet la même indentation qu'une ligne précédente, on sort donc du bloc courant, pour revenir vers le bloc qui le précédait :
BLOCK_1
BLOCK_2 # added indentation, then we start a new code block
BLOCK_1 # we removed indentation, then we get back to BLOCK_1
On ne peut par contre pas revenir dans un bloc qui a été fermé : dans notre exemple, on ne peut pas revenir dans le bloc 2 :
BLOCK_1
BLOCK_2
BLOCK_1
BLOCK_3
if¶
En début de ce chapitre, je disais que nous voulions exécuter du code si une certaine condition était vérifiée, nous y voila avec la structure de contrôle if.
Pour exécuter un bloc de code si une condition est vraie il faut taper :
if CONDITION:
CODE_BLOCK
Conditions¶
Une condition est une sorte de formule qui est soit vraie soit fausse.
Par exemple, on peut tester si une variable a une valeur donnée en utilisant == :
>>> note = 10 # assign a value to variable
>>> note == 11 # check value content against another value
False
>>> note == 10
True
On peut verifier qu'une valeur est differente d'une autre en utilisant != :
>>> note = 10 # assign a value to variable
>>> note != 11 # check value content against another value
True
>>> note != 10
False
On peut aussi tester si une variable est supérieure, inférieure, stricte ou non à une certaine valeur :
>>> note = 10
>>> note <= 10
True
>>> note < 10
False
>>> note >= 10
True
>>> note >10
False
On peut tester qu'une variable est dans un intervale:
>>> note = 10
>>> 0 <= note <= 20
True
>>> 0 <= note < 10
False
>>> 20 >= note >= 10
True
Le mot-clé in¶
Le mot-clé in est très important en Python, et son usage doit être privilegié dans les conditions. Plusieurs cas sont possibles :
- Tester si une valeur est dans une liste :
>>> 5 in range(10)
True
>>> 5 in range(2)
False
- Tester si une clé est dans un dictionnaire :
>>> d = {1: 0, 2: 0}
>>> 0 in d
False
>>> 1 in d
True
- Tester si un texte est dans un autre :
>>> "abc" in "abcdef"
True
>>> "bac" in "abcdef"
False
in est un mot-clé vraiment très pratique, et surtout très lisible non?
"Si cet élément est dans ma liste, alors faire ce bout de code" s'écrit pratiquement comme si on parlait :
if element in my_list:
CODE_BLOCK
La négation : not¶
Le mot clé not, permet d'inverser une condition. Donc si une condition est vraie, alors not condition est fausse, et vice-versa.
Il n'est pas nécessaire d'utiliser des parenthèses pour utiliser le mot clé not, mais cela est vivement conseillé lorsqu'une condition est un peu complexe pour améliorer la lisibilité.
>>> not True
False
>>> not( True )
False
>>> not False
True
Afin d'améliorer la lisibilité, il y a une exception pour le mot clé in, bien sur il est possible d'écrire not élément in liste, mais cela n'est tout de même pas aussi lisible que élément not in liste. Exemple, les deux lignes suivantes sont équivalentes en terme d’exécution, mais la lisibilité de la second est franchement un cran au dessus :
>>> if not 1 in range(5):
... print(True)
>>> if 1 not in range(5):
... print(True)
Les opérations logiques : et et ou¶
Afin de pouvoir faire des conditions un peu plus compliquées, on utilise des mots clés spécifiques : and et or.
and permet de faire un "et logique" entre deux conditions. Pour faire simple, la condition formée par un and entre deux sous conditions n'est vraie que si les deux sous conditions sont vraies :
>>> False and False
False
>>> False and True
False
>>> True and False
False
>>> True and True
True
or permet de faire un "ou logique" entre deux conditions. Il suffit qu'une seule sous condition soit vraie pour que la condition globale soit vraie :
>>> False or False
False
>>> True or False
True
>>> False or True
True
>>> True or True
True
Le cas de la non valeur : None¶
Je n'en ai pas encore parlé, mais il est temps maintenant de vous parler d'une valeur particulière en Python : None.
None permet d'initialiser une variable à une sorte de non-valeur. Ceci est très pratique lorsqu'on veut avoir une variable mais que, par défaut, on ne sait pas encore quoi mettre dedans. Pour revenir à l'exemple de la classe, un élève absent ne doit pas avoir 0 comme note, on pourra dont utiliser 'None' comme note pour cet élève.
>>> marks["McFly"] = None
Pour savoir si une valeur est None, on peut utiliser les doubles égale :
>>> marks["McFly"] == None
True
On peut aussi utiliser un mot clé : is
>>> n is None
True
>>> 1 is None
False
Ceci permet une fois de plus d'améliorer la lisibilité du code, et force est de reconnaître que tout le monde utilise is dès qu'il s'agit de tester si une variable est à None ou non.
Il se peut que l'on ai besoin de tester si une variable n'est pas à None. Auquel cas on peut utiliser not, comme précédemment, mais une fois de plus pour la lisibilité, on peut utiliser is not :
>>> if not( marks["loulou"] is None ):
... marks_sum += marks["loulou"]
>>> if marks["loulou"] is not None:
... marks_sum += marks["loulou"]
Note
a += b permet d'additionner le contenu de la variable a avec le contenu de la variable b, et de l'assigner à la variable a.
Exercice¶
- Écrire une condition qui vérifie qu'une variable est plus grande que 10 et plus petite que 20.
- Écrire une condition qui vérifie qu'une variable est soit positive et plus petite que 15, soit négative et plus petite que -10.
Boucles¶
On peut vouloir exécuter un bloc de code un certain nombre de fois. On fait cela avec une boucle.
Il existe 2 types de boucles en Python : for et while.
for¶
for permet d’itérer sur les éléments d'une liste :
for element in list:
CODE_BLOCK
Ici on voit une autre utilisation du mot-clé in qui permet une très bonne lisibilité de la ligne de code : on veut faire une boucle pour tout élément element dans la liste list.
Dans le bloc de code, la variable element contient un élément de la liste.
Exercice¶
- Afficher les éléments d'une liste quelconque.
- Calculer la somme, à la main, de la liste [1,2,3,4].
Mais alors, vous me direz, comment je fais si je dois faire un certain nombre d’opérations mais que je ne n'ai pas de liste ? Et bien, vous vous souvenez du chapitre sur les listes, on a vu une liste particulière : range(). C'est à elle que nous allons demander de faire le travail :
result = 0
for i in range(4):
result = result + i
print(result)
En fait je ne suis pas honnête à ce moment du jeu : pour les boucles vous trouverez (en Python 2.x) une utilisation majoritaire de xrange() au lieu de range().
Pour faire simple, en Python 2, range() crée la liste en mémoire, alors que xrange() ne crée qu'un élément à la fois : d'où un gain en performance et utilisation mémoire assez monstrueux.
Pour ne plus avoir de problème, en Python 3, il n'y a plus que range(), et il se comporte comme xrange().
Pour vous en rendre compte, (si vous avez un python2 d'installé) essayez ceci :
>>> range(1000000000000000000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
>>> xrange(1000000000000000000)
xrange(1000000000000000000)
En Python 3, aucun soucis avec range():
>>> range(1000000000000000000)
range(0, 1000000000000000000)
Note
Sur windows, python retourne une erreur quand l'entier est plus grand que 1000000000. Sous linux je n'ai eu aucun soucis avant 1000000000000000000 ...
while¶
while permet d'exécuter un bloc de code tant qu'une condition est vraie :
while condition:
CODE_BLOCK
Attention, il est très facile de se retrouver dans une "boucle infinie" avec while !
Exercice¶
Calculer la liste des entiers jusqu’à 15 en utilisant une boucle
while.
Sortir du bloc avec/sans sortie de la boucle¶
Il est possible de faire en sorte que Python n'aille pas plus loin dans l’exécution du bloc d'une boucle (for ou while) afin de passer à l'élément suivant. Pour cela on utilise le mot-clé continue. Par exemple :
for i in range(2):
if i == 1:
continue
CODE_BLOCK
Ici, on va donc exécuter un bloc de code que s'il est différent de 1, car dans ce cas, on "continue".
Si on veut sortir de la boucle en elle même, on peut utiliser break. Il s'utilise comme continue, mais permet de stopper la boucle :
while True:
if condition:
break
CODE_BLOCK
Exercice¶
Donner l'entier pour lequel la somme de tous les entiers avant lui (y compris cet entier) devient plus grande que 123456 en utilisant une sortie de boucle.
Les fonctions¶
Voila, maintenant, nous savons mettre des valeurs dans des variables, faire en sorte d’exécuter un bloc de code en fonction d'une condition, et même faire des boucles pour itérer sur les éléments d'une liste, etc.
Mais il semble nous manquer quelque chose pour organiser notre code et faire en sorte que l'on puisse réutiliser du code d'un script à l'autre.
Cette brique qui va nous permettre cela, c'est la fonction.
En mathématiques, une fonction est une relation entre un ensemble d’entrées (variable) et un ensemble de sorties (image), avec la propriété que chaque entrée est liée au plus à une unique sortie. Un exemple de fonction est la fonction qui à tout nombre noté x associe son carré.
En informatique, c'est quasiment semblable (à l'exception de l'unicité de la valeurs de sortie, surtout avec des nombres aléatoires ;) ).
Une fonction est un bloc de code qui prend des arguments en entrée et qui retourne une (ou des) valeur(s) en sortie.
Une fonction a un nom qui permet de l'appeler, comme en mathématiques, et comme une variable. D'ailleurs, en Python, une fonction est une variable de type function.
Pour définir une fonction on fait comme ça :
def name_of_function():
CODE_BLOCK
Ceci défini une fonction qui ne prend pas de paramètre (oui c'est possible), et qui ne retourne rien. Une telle fonction pourrait très bien allumer une lampe, ou l'éteindre.
Si on veut rajouter des argument on rajoute leur nom entre les parenthèses, et séparés par des virgules :
def set_temperatur(wanted_temperature):
CODE_BLOCK
def show_color(red_intensity, red_intensity, red_intensity):
CODE_BLOCK
Dans le premier cas, dans tout le bloc de code, on a accès à une variable wanted_temperature, et dans le second exemple, on a accès aux trois variables pour le rouge, le vert et le bleu.
Pour retourner une valeur, on utilise le mot clé return, comme ceci :
def pi():
return 3.14159
Voila, on sait maintenant écrire une fonction, mais comment l'appeler ?
Tout simplement en utilisant son nom avec les parenthèses :
>>> def pi():
... return 3.14156
...
>>> print(pi())
3.14159
Si la fonction prend des paramètres, on les passe dans les parenthèses :
>>> def echo(valeurs):
... print(valeurs)
...
>>> echo(1)
1
>>> echo("ABC")
'ABC'
>>> echo([1,2])
[1,2]
Comme je le disais, une fonction en Python est aussi une variable :
>>> print(echo)
<function echo at 0x7f7ad7bf4668>
>>>> type(echo)
<type 'function'>
En fait dans ce cas, echo est une variable qui pointe vers une fonction qui est stockée en mémoire à l'adresse 0x7f7ad7bf4668 (ce chiffre sera différent à chaque définition de fonction).
Exercice¶
- Écrire une fonction qui retourne la valeur absolue d'un nombre
- Utiliser cette fonction pour l'appliquer sur tous les chiffres d'une liste.
Documentation¶
Il est désormais temps de parler d'une chose qui rebute en général les développeurs : la documentation.
Ce n'est pas parce que les gens rechignent à le faire que cela n'est pas à faire.
La simple idée de relire un code qui n'est pas documenté n'est pas une chose qui m'attire. Quand bien même s'il s'agit de son propre code, quelques mois plus tard on ne sait plus forcement ce que l'on a fait, ni même à quoi sert un script, quelles sont ses options, ou à quoi sert telle ou telle fonction.
Il va donc falloir s'y mettre et pas à la dernière minute, où la tache semble si grande que la plupart des gens la bacle, ou même, la snobe. Le meilleur moyen est donc d'écrire notre documentation au fil de l'eau.
En Python, la documentation fait partie prenante du langage, et peut même être recupérée avec l'introspection. Vous vous souvenez de help() ? Et bien il retourne ce que les développeurs écrivent comme documentation.
Pour documenter une fonction, il faut rajouter un texte après sa définition (son nom). Le plus commun est d'utiliser les triples doubles quotes :
def my_function():
"""This is the documentation of my_function."""
CODE_BLOCK
print(help(my_function))
'This is the documentation of my_function.'
Excercice¶
Documentez les fonctions que vous aviez créées lors du point précédent.
Les modules¶
Une autre notion qui fait de Python un langage à part c'est la notion de module.
Un module en Python est une collection de variables et de fonctions qui permettent d'étendre le langage. Bien qu'il y ait des modules développés par des développeurs partout dans le monde, une force de Python est d'être livré avec un certain nombre de ces modules directement. Python essaie de maintenir une philosophie batteries included, grâce aux modules qui sont livrés en standard. Ceux-ci permettent d'interagir avec l'OS (listing de fichiers, création et suppressions de fichiers), mais aussi de pouvoir gérer le temps, ou alors les fichiers CSV, de faire du JSON, de faire du multithreading, ou multiprocessing, de dialoguer avec des bases de données, de faire du réseau, de faire office de server web, etc.
Pour connaître la liste des modules livrés de base avec Python, vous pourrez vous référer à la page suivante de la documentation de Python.
Afin de pouvoir utiliser un module il faut l'importer de cette façon :
import MODULE_NAME
Ensuite on peut utiliser la document ation officielle de ce module, mais aussi l'introspection (dir() ou bien help()), pour savoir quelles variables ou fonctions ce module met à disposition.
On utilise les variables et les fonctions en utilisant le nom du module, un point, ainsi que le nom de la variable/fonction, comme ceci :
import MODULE
MODULE.useful_function()
os¶
Ce module permet d'interagir avec le systeme d'opération de votre ordinateur.
os permet notement de :
- Connaitre et changer les variables d'environement,
- Lancer des commandes du système,
- Connaitre et changer le répértoire courant d'execution,
- Connaitre le nom de l'utilisateur,
- ...
Exemple :
>>> import os
>>> os.environ["USER"]
'fabien'
>>> os.getlogin() # Linux only
'fabien'
>>> os.system("echo Hello!")
Hello!
>>> os.chdir("/")
>>> os.getcwd()
'/'
Note
getlogin n'est disponible que sous linux, pour avoir le nom de l'utilisateur de manière portable on peut utiliser la fonction getuser() du module getpass.
sys¶
Permet d'obtenir des informations sur l'état de l'interpreteur Python.
Par exemple quelle version de Python est utilisée :
>>> import sys
>>> print(sys.version_info)
sys.version_info(major=3, minor=8, micro=5, releaselevel='candidate', serial=1)
math¶
Vous souvenez-vous du fait que Python ne savait pas faire de la trigonométrie ? Et bien c'est faux, il sait le faire c'est juste qu'il faut utiliser le module de mathématiques pour cela.
Ce module nous met donc à disposition tout un tas de fonctions comme copier le signe d'un nombre sur un autre, connaitre la valeur entière la plus proche d'un nombre, calculer un factoriel, des puissances de logarithmes, des sinus/cosinus, etc.
>>> import math
>>> math.sin(math.pi)
1.2246467991473532e-16
Et oui, les microprocesseurs ne sont pas hyper précis, mais bon 10^-16 c'est proche de 0 quand même.
time¶
Ce module met à disposition un certain nombre de fonctions relatives à la gestion du temps, mais aussi la gestion de l'heure.
Il permet notement de connaitre l'heure courante avec une précision generalement meilleure que la seconde, mais cela ne peut pas être garanti et dépends du système.
>>> import time
>>> time.time()
1547158168.292978
Ceci peut être très interressant pour faire de l'étude de performance grossière (à la seconde près), mais si on veut mieux, il faut plutot utiliser time.clock() qui est de l'ordre de la microseconde.
random¶
random, comme son nom l'indique, va permettre d'ajouter de l'aléatoire dans un script. Comme initialiser une variable avec un entier entre deux bornes, ou alors un nombre réél entre 0 et 1 :
>>> import random
>>> random.random()
0.9406027006427641
>>> random.randint(0, 30)
9
random est aussi capable de bien d'autres choses, par exemple mélanger une liste, ou alors retourner une sous-liste aléatoire à partir d'une liste de départ.
Autres¶
Il y a bien d'autres modules displonibles avec l'installation par défaut de Python, et je ne vais pas tous les énumérer ici.
Sachez tout de même deux choses : * Il y a aussi de très nombreux modules développés par des developpeurs tiers (gratuits ou non). * Certains modules tiers se sont vite imposés comme des incontournables pour leur domaine d'application : * NumPy pour le calcul scientifique, * pandas pour l'analyse de données, * PIL/Pillow pour le traitement d'image, * TensorFlow pour le machine learning * ...
Interaction avec l'utilisateur : poser des questions et écouter les réponses¶
Lors de l'écriture de scripts, il se peut que l'on ait besoin de poser des questions à l'utilisatuer afin de rendre le script "interactif".
En Python 3.8 il faut passer par la fonction input().
Elle prend en paramètre optionel un texte à afficher avant de poser la question à l'utilisateur :
>>> s = input('--> ')
--> Monty Python's Flying Circus
>>> s
"Monty Python's Flying Circus"
Exercice¶
- Écrire un script qui demande à l'utilisateur de deviner un chiffre entre 1 et 10. Il devra taper des chiffres jusqu'à ce qu'il trouve le bon résultat.
- Faire en sorte que le script résiste au fait que l'utilisateur écrive autre chose que des chiffres.
Donner des arguments à un script¶
Il existe une façon simple et (au moins) une façon avancé de gérer les paramètres d'un script. Je me contenterais ici de donner la façon simple, mais sachez que la version compliqué peut être trouvé sur cette page de la documentation officielle.
La façon simple est d'utiliser le module sys qui met à disposition une variable argv qui contient tous les éléments de la ligne de commande qui a été utilisée pour lancer Python.
>>> import sys
>>> sys.argv
['']
En mode interactif, ceci n'a que peu d'intérêt, mais si on écrit un script on peut se servir de cette liste pour connaitre les options qu'un utilisateur a ajouté en plus du script dans la ligne de commande.
Écrivons ce script :
import sys
print(sys.argv)
Maintenant, lançons le avec plusieurs options :
$ python argv_printer.py
['argv_printer']
$ python argv_printer.py argument_1
['argv_printer.py','argument_1']
Comme on peut le voir, argv est une liste remplie avec les options que l'utilisateur a ajouté dans sa ligne de commande quand il a lancé son script.
Amusons nous avec turtle¶
turtle est un module de dessin basé sur le "jeu de la tortue". La philosophie derrière est très simple : une tortue tiens un crayon, elle peut avancer d'une certaine distance, ou tourner a gauche/droite d'un certain angle.
Il convient de faire le code suivant pour démarrer la tortue et lui faire dessiner une ligne droite, tourner à gauche, et dessiner une autre droite :
>>> import turtle
>>> t = turtle.Turtle() # Create a new windows for turtle to move on
>>> t.forward(100)
>>> t.right(90)
>>> t.forward(100)
Dessiner un triangle¶
Un peu de maths : un triangle est un polygone à 3 cotés (ou 3 sommets). La somme des angles d'un triangle vaut 180°.
On pourra donc finir de dessiner un triangle avec le code suivant :
>>> t.right(90+45)
>>> import math
>>> t.forward( math.sqrt( 100**2 + 100**2 ) )
Exercice¶
- Écrire une fonction qui permet de dessiner un triangle isocèle en fonction de son point de départ en bas à gauche, et de la longueur de ses cotés.
- Comment faire pour que l'on ne dessine pas entre deux triangles ?
Dessiner un carré¶
Exercice¶
Comme pour le triangle, écrire une fonction pour dessiner un carré.
Dessiner un cercle¶
Exercice¶
- Idem.
- Écrire une fonction pour dessiner une rosace.
Manipulations du système de fichiers¶
Création d'un fichier et écriture¶
Afin de créer un ficher il faut utiliser la fonction open(). Elle prend deux paramètres :
un texte qui donne le nom du ficher à créer, et un autre texte qui donne le mode d'ouverture du fichier ('w' pour l'écriture; 'a' pour écrire à la fin du ficher, 'r' en mode lecture).
Le nom du ficher est en fait un chemin qui peut être soit absolu, soit relatif au répértoire courant d'éxécution.
Ainsi pour créer le fichier toto.txt dans le répértoire courant il faut procéder ainsi :
>>> fd = open("toto.txt","w")
>>> fd.close()
Nous avons ainsi ouvert le fichier toto.txt en écriture, et nous l'avons fermé aussitôt. Si on ouvre ce fichier dans un éditeur, on verra qu'il s'agit d'un ficher vide.
Note
il est nécessaire de fermer le fichier afin que son contenu ne soit réellement écrit et de pouvoir l'ouvrir dans un autre éditeur.
Python a introduit il y a peu la notation with, qui permet, notamment, de gérer les fichiers plus facilement. Voilà le même exemple, voyez comme il n'est plus nécessaire de fermer le fichier, la sortie du bloc de code de with entraine sa fermeture :
>>> with open("toto.txt", "w") as fd:
... pass
...
C'est bien beau, mais comment écrire dans le fichier?
C'est très simple, soit en specifiant le paramètre file à print, soit en utilisant la méthode write du descripteur de fichiers.
>>> with open("toto.txt", "w") as fd:
... print("My first line", file=fd)
... fd.write("#My second line\n")
...
Voila, ce n'est pas plus compliqué que cela. Si on voulait ajouter des lignes au fichier toto.txt, il aurait juste suffit de l'ouvrir en mode "a" (comme append) et écrire dedans.
Lecture d'un fichier¶
Pour lire un fichier c'est tout aussi simple. Il suffit de l'ouvrir en mode lecture, et ensuite on utilise le descripteur de fichier dans une boucle ce qui permet d'itérer sur les lignes du fichier :
>>> with open("toto.txt", "r") as fd:
... for line in fd:
... if line.startswith("#"):
... print(line)
...
'#My second line'
Exercice¶
- Lire le fichier toto.txt et ne copier que les lignes qui ne commencent pas par
#dans un fichier toto2.txt- Lire le fichier toto.txt et le copier 3 fois de suite dans toto3.txt
Lister le contenu d'un répértoire¶
Pour lister le contenu d'un répértoire, il va falloir utiliser des méthodes du module os.
os.listdir(): Retourne la liste des fichiers et répértoires qui sont contenus dans le répértoire donné en paramètre à la fonction.os.path.join(): Concatène 2 chemins (ou plus) en utilisant le séparateur de chemin du système sur lequel le script tourne.os.path.isdir(): RetourneTruesi, et seulement si, le chemin passé en paramètre correspond à un répértoire.os.path.isfile(): RetourneTruesi, et seulement si, le chemin passé en paramètre correspond à un fichier.
Ainsi, si on veut écrire une fonction qui retourne seulement les fichiers dans un chemin, et une autre qui retourne les répértoires, on pourra faire comme cela :
def list_files_in_directory(path):
""" Returns list of files only within given path."""
result = list()
for item in os.listdir(path):
filepath = os.path.join(path, item)
if os.path.isfile(filepath):
result.append(filepath)
return result
def list_dirs_in_directory(path):
""" Returns list of directories only within given path."""
result = list()
for item in os.listdir(path):
filepath = os.path.join(path, item)
if os.path.isdir(filepath):
result.append(filepath)
return result
Exercice¶
Écrire un script qui prend un seul paramètre, un chemin, et qui retourne tous les fichiers de manière récursive.
Supprimer, Déplacer ou Copier des fichier¶
Ici aussi il faudra utiliser le module os :
os.remove(): Supprime le fichier dont le chemin est passé en paramètreos.rename(old, new): Déplace un fichier passé en premier paramètre pour le placer et renommer à l'endroit pointé par le second paramètre.
MAIS, il n'y a pas de fonction de copie... Pour cela il faudra utiliser le module shutil qui continent plusieurs fonctions de copie :
shutil.copyfile(old, new): Copie un fichiershutil.copy(old, new): Copie un fichier ainsi que les autorisations du fichier.shutil.copy2(old, new): Copie un fichier ainsi que ses méta-données.
Exercice¶
Écrire votre propre fonction de copie d'un fichier.
Array Slicing¶
Sous ce terme barbare se cache une fonctionnalité très intéressante afin de traiter des données contenues dans une liste.
Quand on utilise les [], on peut faire beaucoup plus que de se limiter à donner un simple index.
>>> l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`
>>> l[2,4] # l[start:end] -> items from start through end-1
[2,3]
>>> l[7:] # l[start:] -> items from start through the rest of the array
[7,8,9]
>>> l[:4] # l[:end] -> items from the beginning through end-1
[0,1,2,3]
>>> l[:] # l[:] -> a copy of the whole array
[0,1,2,3,4,5,6,7,8,9]
On peut aussi utiliser un parametre suplementaire qui defini l'incrément :
>>> l[2:9:3] # l[start:end:step] -> items from start through not past end, by step
[2,5,8]
Ce qui est important à retenir, c'est que la valeur de fin est la première valeur à ne pas être inclue. Ainsi, le nombre d'éléments dans le slice sera end-start (à moins de changer d'incrément).
Le départ ou la fin peuvent être des nombres négatifs ! Donc :
>>> l[-2:] # last two items in the array
[8,9]
>>> l[:-2] # everything except the last two items
[0,1,2,3,4,5,6,7]
De la même manière, l'incrément aussi peut être négatif :
>>> l[::-1] # all items in the array, reversed
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> l[1::-1] # the first two items, reversed
[1,0]
>>> l[:-3:-1] # the last two items, reversed
[9,8]
>>> l[-3::-1] # everything except the last two items, reversed
[7,6,5,4,3,2,1,0]
Python est encore une fois du coté du développeur afin de lui simplifier la vie. Quand on demande plus d'éléments qu'il n'y en a dans la liste, Python retourne ce qu'il peut.
Note
on peut faire la même chose avec des tuples, le résultat du slice sera un tuple.
Note
on peut utiliser le slicing sur des textes aussi ! Ceci permet d'obtenir un sous texte de façon simple :
>>> t = "abcdefghij"
>>> t[-3::-1]
'hgfedcba'
Doctest, quézako ?¶
Il est très important de documenter son code, nous l'avons déjà vu. Mais il est tout aussi important de le tester. Ce que permet de faire le module doctest c'est de faire les deux en même temps, ou quasiment.
En effet, lors de l'écriture de la documentaiton, on va pouvoir ajouter des tests sur le code. Cela va même permettre de montrer des exemples d'utilisation ainsi que le resultat espéré, au sein même de la documentation.
Voici un exemple :
def absolute(x):
""" Given a numeric input x, returns the value of x without sign.
If x is not numeric, then return None
>>> absolute(1)
1
>>> absolute(-1)
1
>>> absolute("a") is None
True
>>> absolute(0)
0
"""
if type(x) not in (type(1), type(1.5)):
return None
if x >= 0:
return x
else:
return -x
Note
On peut se servir de cela pour faire du "Test Driven Developement" (TDD). On écrit alors le squelette de la fonction avec sa documentation et ses tests !
Mais alors, comment tourner les tests ? Très simple, il faut copier le code si-dessus dans un fichier TrainingPython/DocTests/first_doctests.py_ (doctest n'a d'utilité qu'avec des scripts), puis lancer la commande suivante :
$ python -m doctest Training_Python/DocTests/first_doctests.py
Il n'y a rien dans la sortie : c'est normal, tous les tests passent! Si on veut plus de details, il faut passer l'option verbose (-v en abrégé) :
$ python -m doctest -v Training_Python/DocTests/first_doctests.py
Trying:
absolute(1)
Expecting:
1
ok
Trying:
absolute(-1)
Expecting:
1
ok
Trying:
absolute("a") is None
Expecting:
True
ok
Trying:
absolute(0)
Expecting:
0
ok
1 items had no tests:
first_doctests
1 items passed all tests:
4 tests in first_doctests.absolute
4 tests in 2 items.
4 passed and 0 failed.
Test passed.
Notre fonction à bel et bien passé ses 4 tests !
Exercice¶
Écrire une fonction en utilisant la méthode TDD avec
doctestqui valide le cahier des charges suivant :
- si l'entrée est un entier, retourne son opposé,
- si l'entrée est un flottant, retourne sa valeur absolue,
- si l'entrée est une liste, la fonction s'appelle elle même sur chacun des élements de la liste et retourne la liste résultante,
- si l'entrée est un texte, retourne un caractère sur 2 de ce texte.
Exemple concret : implémentation de soft timeouts dans un but de test de performance non bloquant¶
Pour faire des benchmarks, on peut executer des commandes les unes après les autres et tout stocker dans un dictionnaire.