Fabien Boutantin
Janvier 2019
Merci à Benjamin et Louis pour leur aide active.
$ sudo apt install python
PATH :C:\Python27\ dans le PATH s'il n'y est pas déjàUn site sur des bonnes pratiques Python.
Ou notre premier code Python
$ python
Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
Cela veut dire plusieurs choses :
>>>)C'est parti, tapez :
>>> print "Hello, world!"
Vous devriez avoir quelque chose comme cela à l'écran maintenant :
>>> print "Hello, world!"
Hello, world !
print"print "Hello, world!"
Permet donc d'écrire le texte Hello, world ! dans le terminal.
>>> quit()
$
>>> 1+1
2
>>> ( 1 + 2 * 12 ) / 3
8
Mais, la division est fausse, non ?
25/3 ça ne vaut pas 8 !
En Python, quand on divise des entiers, on fait la division entière.
>>> (1+3j)**2
(-8+6j)
>>> sinus(3.14159)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sinus' is not defined
<stdin>),sinus est inconnu pour Python, il n'est pas défini.Mais une minute, on nous parle de nom de fichier, de scripts Python, etc. Comment ça marche ?
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 :
print "Hello, world!"
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 !
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 :
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.
La lisibilité est importante.
Pour rendre du code plus lisible on peut utiliser des lignes d'explications 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
print 1+1 # expected result : 2
Comme je l'ai déjà dit, Python est un langage simple, mais complet. En effet, la lecture du code est importante (Python zen), mais les types de données que peut manipuler (facilement) Python sont énormes.
intComme on l'a vu récemment, on peut manipuler des entiers :
>>> 3*5
15
floatOn peut aussi manipuler des nombres réels :
>>> 3.14159*2
6.28318
Et oui, on l'a déjà vu aussi:
>>> (3+2j)**3
(-9+46j)
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
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.
>>> """Hello
... world"""
'Hello\nworld'
Note : L'invite de commandes Python mets trois petits points lorsque la commande est sur plusieurs lignes.
Note 2 : Dans la majeure partie des langages de programmation, \n signifie "saut à la ligne".
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 :
Exemple :
>>> 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.
_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.
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 ?
list()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 remplir une liste 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]]
Pour accéder à un élément donné, connaissant son ordre dans la liste, on utilise les crochets :
>>> misc_list[1]
'a'
>>> misc_list[0]
1.0
On peut aussi partir de la fin en utilisant un index négatif : -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
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)
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.
tupleLes 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 performances 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)
Comment échanger le contenu de deux variable ?
(Réponse : a,b = b,a)
setUn set est comme une liste, mais diffère sur 2 points :
On peut créer dynamiquement un ensemble d'élements uniques par exemple, à partir d'une liste :
>>> uniq_set_of_values = set([1, 2, 1, 3, 1, 4, 2])
>>> uniq_set_of_values
set([1, 2, 3, 4])
Ce deuxième point est la principale raison d'être des sets.
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])
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.
Un dictionnaire vide peut se créer avec la fonction dict():
>>> marks = dict()
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
Sur un dictionnaires il est intéressant d'avoir la liste de clés (keys()) et la liste des valeurs (values()) :
>>> marks.keys()
['riri', 'fifi', 'toto', 'loulou']
>>> marks.values()
[12, 14, 2, 20]
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 a docs.python.org, ou bien jouez sur HackerRank.
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() affiche l'aide d'un objet.
Interactif dans la console
Dans un script :
Donne le "texte" de l'aide, telle qu'on peut la voir sur docs.python.org
Il faut passer par print pour voir le texte.
>>> help(set)
Help on class set in module __builtin__:
class set(object)
| set() -> new empty set object
| set(iterable) -> new set object
...
type()type() done le type d'une variable ou d'un objet.
>>> d = dict()
>>> type(d)
<type 'dict'>
>>> type(3.14159)
<type 'float'>
dir()dir() donne la liste de ce que propose un objet en Python.
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.
À 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.
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.
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.
Ensemble de lignes de codes que l'on veut exécuter "d'un bloc".
Très souvent délimité par un indicateur (un caractère) de début et de fin (un autre caractère). En C++ :
{CODE_BLOCK}
Indentation pour rendre le code plus clair :
{
CODE_BLOCK
}
Seulement une bonne pratique, pas d'obligations.
En Python pas de séparateur, il faut indenter. Readability counts
Pour crééer des blocs, il faut changer l'indentation :
BLOCK_1
BLOCK_2
Un retrait d'intentation fait revenir dans le bloc parent :
BLOCK_1
BLOCK_2 # added indentation: new code block
BLOCK_1 # we removed indentation: 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
ifEn 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
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 tester si une variable a une valeur different 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 en une fois qu'une variable est est dans un intervale:
>>> note = 10
>>> 0 <= note <= 20
True
>>> 5 < note < 10
False
inLe mot-clé in est très important en Python, et son usage doit être privilegié dans les conditions. Plusieurs cas sont possibles :
in : Tester dans une liste>>> 5 in range(10)
True
>>> 5 in range(2)
False
in :Tester dans un dictionnaire>>> d = {1: 0, 2: 0}
>>> 0 in d
False
>>> 1 in d
True
in : Tester un texte dans un autre>>> "abc" in "abcdef"
True
>>> "bac" in "abcdef"
False
in - Readabilityin 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
notLe mot clé not, permet d'inverser une condition. Donc si une condition est vraie, alors not condition est fausse, et vice-versa.
Les parenthèses ne sont pas nécessaires, mais conseillées lorsque la condition devient complexe, pour améliorer la lisibilité.
>>> not True
False
>>> not( True )
False
>>> not False
True
not inin.not élément in liste.élément not in listeExemple : deux codes équivalents, mais le second est bien plus facile à lire et à comprendre !
>>> if not 1 in range(5):
... print True
>>> if 1 not in range(5):
... print True
Afin de pouvoir faire des conditions un peu plus compliquées, on utilise des mots clés spécifiques : and et or.
andand permet de faire un "et logique" entre deux conditions.
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
oror 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
NoneJe 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
is None dans les conditionsPour 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.
is not None dans les conditionsIl 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.
- É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.
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.
forfor 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.
- 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 sans rentrer dans les détails, 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 vous en rendre compte, essayez ceci :
>>> range(1000000000000000000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
>>> xrange(1000000000000000000)
xrange(1000000000000000000)
whilewhile 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 !
Calculer la liste des entiers jusqu’à 15 en utilisant une boucle
while.
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 xrange(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
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.
Nées du besoin d'organiser notre code pour ne pas se répéter.
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é.
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.
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
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).
- Écrire une fonction qui retourne la valeur absolue d'un nombre
- Utiliser cette fonction pour l'appliquer sur tous les chiffres d'une liste.
En Python, la documentation fait partie prenante du langage, et peut même être recupérée avec l'introspection. help() retourne la documentation écrite par les développeurs.
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.
Simplement en rajoutant 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 will print 'This is the documentation of my_function.'
Documentez les fonctions que vous aviez créées lors du point précédent.
La notion de module fait de Python un langage à part.
Collection de variables et de fonctions qui permettent d'étendre le langage.
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()
osCe module permet d'interagir avec le systeme d'opération de votre ordinateur.
os permet notemment de :
os : exempleExemple :
>>> import os
>>> os.getlogin()
'fabien'
sysPermet 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=2, minor=7, micro=15, releaselevel='candidate', serial=1)
mathBesoin d'utiliser le module de mathématiques pour faire toutes sortes de calculs.
math propose 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.
timeCe 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.
randomrandom, 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.
Il y a bien d'autres modules displonibles avec l'installation par défaut de Python.
Lors de l'écriture de scripts, on a parfois besoin de poser des questions à l'utilisatuer afin de rendre le script "interactif".
En Python 2.7 il faut passer par la fonction raw_input().
Elle prend en paramètre optionnel un texte à afficher avant de poser la question à l'utilisateur :
>>> s = raw_input('--> ')
--> Monty Python's Flying Circus
>>> s
"Monty Python's Flying Circus"
- É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.
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.
turtleturtle 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)
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 ) )
- Écrire une fonction qui permet de dessiner un triangle isocèle en fonction de son point de depart en bas à gauche, et de la longueur de ses cotés.
- Comment faire pour que l'on ne dessine pas entre deux triangles ?
Comme pour le triangle, écrire une fonction pour dessiner un carré.
- Idem.
- Écrire une fonction pour dessiner une rosace.
open() permet de créer un fichier.'w' pour l'écriture, 'a' pour écrire à la fin du ficher, 'r' en mode lecture.Créer le fichier toto.txt dans le répértoire courant :
>>> fd = open("toto.txt","w")
>>> fd.close() # Don't forget to 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.
with openPour faciliter l'ouverture et la fermeture de fichier, on peut utiliser with.
À la sortie du bloc, le fichier sera fermé automatiquement :
>>> with open("toto.txt", "w") as fd:
... pass
...
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 sont 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, notement, de gerer les fichiers plus facilement. Voila 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 :
Soit avec une forme spéciale de print
Soit en utilisant la méthode write du descripteur de fichiers.
>>> with open("toto.txt", "w") as fd:
... print >>fd, "My first line"
... 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.
Ouverture en mode lecture
Utiliser le descripteur de fichier dans une boucle pour 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'
- 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
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() : Retourne True si, et seulement si, le chemin passé en paramètre correspond à un répértoire.os.path.isfile() : Retourne True si, et seulement si, le chemin passé en paramètre correspond à un fichier.osdef 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
Écrire un scripte qui prend un seul parametre, un chemin, et qui retourne tous les fichiers de manière récursive.
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.Écrire votre propre fonction de copie d'un fichier.
Permet de traiter facilement des données d'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 paramètre supplémentaire qui defini l'incrément :
# l[start:end:step] # start through not past end, by step
>>> l[2:9:3]
[2,5,8]
Ce qui est important a 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 2 : 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 ?Le module doctest permet de faire la documentation et les tests en même temps, ou quasiment.
doctest : Exempledef 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 doc et ses tests !
doctest : Utilisation (1/2)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
doctest : Utilisation (2/2)L'affichage est vide : tous les tests passent ! Plus de détails avec l'option verbose (-v en abrégé) :
$ python -m doctest -v Training_Python/DocTests/first_doctests.py
Trying:
absolute(1)
Expecting:
1
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 !
É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 resultante
- si l'entrée est un texte, retourne un caractère sur 2 de ce texte
soft timeoutsImplémentation de soft timeouts dans un but de tests de performances non bloquants.
Pour faire des benchmarks, on peut executer des commandes les unes après les autres en prenant le temps de chacune d'elles.
| Table of Contents | t |
|---|---|
| Exposé | ESC |
| Presenter View | p |
| Source Files | s |
| Slide Numbers | n |
| Toggle screen blanking | b |
| Show/hide next slide | c |
| Notes | 2 |
| Help | h |