Introduction au Python.
Python est un langage de programmation très puissant mais mais aussi simple à apprendre. Venez découvrir Python avec son interpréteur et ses généralités.
Introduction
Je vais introduire la base de Python avec vous. Cependant, je suppose certains prérequis. Premièrement je considère que vous savez ce qu'est un langage de programmation et que Python est déjà installé sur votre ordinateur. Si ce n'est pas le cas il existe déjà de nombreuses explications sur internet notamment ici. Pour ma part je travaille sur Ubuntu avec Python2.7 mais vous pouvez utiliser la version 3, je tenterai d'expliquer les différences aux moments adéquats. Selon moi une personne connaissant Python2.7 saura très bien faire du Python3, l'inverse n'est pas toujours vrai et nous verrons pourquoi.
Cours du jour
C'est parti pour la leçon du jour. Au programme: les généralités de ce langage, un nouvel interpréteur et la découverte des types et des variables. Plus globalement nous répondrons à la question: qu'est-ce que Python?
Langage interprété
Il faut d'abord savoir qu'il existe deux types de langages: interprété ou compilé! Grossièrement un langage compilé doit, avant d'être exécuter, être traduit en binaire (un autre langage). Un langage interprété quant à lui va le traduire au fur et à mesure. Comme vous pouvez vous en douter avec le titre Python est interprété !
Afin de l'utiliser il faut donc un interpréteur.
Ce dernier récupère les instructions que nous lui donnons et les effectue
directement. Pour avoir votre premier interpréteur il vous suffit d'entrer
$ python dans votre terminal. Vous êtes alors dans votre
interpréteur que vous pouvez quitter avec la commande >>> quit()
(ce qui est plutôt utile). Il s'agit de l'interpréteur basique, il
fonctionne très bien mais j'ai mieux à vous proposer... ;)
Le problème de l'interpréteur basique est qu'il n'y a ni autocomplétion ni de coloration syntaxique, ce qui n'est pas super agréable. Je vous conseille donc d'utiliser bpython ou ipython qui sont deux excellents outils. Nous utiliserons bpython mais sachez que ipython possède énormément de fonctions très intéressantes mais j'en parlerai plus tard avec Jupyter. De plus bpython est plus simple et suffira largement pour ce que nous allons faire! Pour l'installer vous pouvez suivre les indications ici. Bien entendu vous pouvez très bien garder l'interpréteur initial, il sera juste moins agréable à utiliser...
Vous avez votre interpréteur? Que les choses sérieuses commencent!
Notions générales
Parlons peu, parlons Python! Afin de savoir utiliser un outil il faut, selon moi, le comprendre un minimum. Je ne vais pas rentrer dans des détails très pointus (que je ne maitrises pas forcément) mais je vais tenter de vous apprendre certaines choses sur ce langage. Premièrement il faut savoir qu'il existe plusieurs Python. Oui je sais c'est un peu bizarre mais l'implémentation de référence est CPython. C'est un interpréteur de bytecode écrit en C. Cependant, il en existe d'autres comme Jython pour Java, Pyfort pour Fortran ou PyPy pour Python. Oui, cette dernière est une mise en œuvre de Python... Avec elle-même. Je vous laisse faire plus de recherches si vous êtes intéressés.
La deuxième particularité est son typage. Python est un langage au typage fort et dynamique. Qu'est-ce que ça signifie? Pour ceux qui ne connaissent pas il y a les typages fort ou faible et statique ou dynamique. La plus part des langages distinguent un entier naturel (int[eger]) et les réels (float), les caractères simples et les chaines de caractères, etc. On dit qu'ils sont fortement typés (exemple: C++), à l'inverse ceux qui le sont faiblement considèrent les variables 'juste' comme des nombres ou une autre catégorie regroupant plusieurs types (exemple: JavaScript). Ensuite il peut être statique, c'est à dire qu'une fois la variable créée elle a un type fixe qui ne changera pas. A l'inverse avec un typage dynamique un objet peut très bien changer par l'appelle d'une fonction par exemple. Ceci dépend de la muabilité...
La quoi??? La muabilité! Je sais le nom est barbare mais
c'est quelque chose d'assez simple. Déjà il faut savoir que Python est un
langage introsectif: c'est-à-dire que tout est objet! Il s'agit un
conteneur qui a différentes informations et fonctions. Nous reverrons ça dans
une prochaine leçon... Revenons pour le moment aux termes 'muable' et
'immuable'. Immuable signifie juste que la variable ne change pas en appelant
une fonction dessus, la valeur reste donc la même tandis qu'un objet muable
va changer de valeur 'in place'. Il est important d'avoir cette précision
lors de l'utilisation d'un type afin d'éviter les mauvaises surprises. Mais
comment on sait si un type est muable ou pas? Et bien il existe des fonctions
'spéciales' qui s'écrivent comme ceci: __nomfunction__. Il
s'agit de fonctions "cachées" que nous n'appelons (sauf cas spéciaux) jamais
directement mais par d'autres moyens. Par exemple le + appelle
en réalité __add__. Et bien il faut savoir que les types
immuables ont la fonction __hash__ ce qui n'est pas le cas
pour la plupart des muables.
Ok, c'est très bien tout ça mais comment je fais comment
pour voir les fonctions d'une classe? Et bien je vous présente deux amies:
les fonctions dir() et help()! Commençons par
le plus évident: help() permet d'obtenir la documentation
liée à un objet, classe ou fonction. dir() quant à lui permet
de voir toutes les méthodes normales et spéciales. Voici un petit exemple:
>>> dir("mot") ['__add__', '__class__', ..., ''__hash__', '__init__', ..., 'upper', 'zfill'] >>> help("mot".upper) S.upper() -> string Return a copy of the string S converted to uppercase.
Bon parler c'est bien joli mais si on codait?
Premières instructions
Chaines de caractères
Maintenant nous allons être un peu plus actif, lancer
$ bpython dans votre terminal et on va travailler un peu!
Le but est de découvrir les types principaux, voir les premières normes
syntaxiques et singularités. Aller, on commence avec quelque chose de
super simple: les chaines de caractères! En anglais on le traduit part
string ce qui est raccourci en str.
>>> my_string = "My name is FtZzy !" >>> dir(my_string) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
Alors c'est un nouveau type donc premier réflexe: muable
ou non? On retrouve le fameux __hash__ donc on dirait que non.
Nous nous intéressons par exemple à la fonction lower().
>>> help(my_string.lower) S.lower() -> string Return a copy of the string S converted to lowercase. >>> my_string.lower() 'my name is ftzzy !' >>> my_string "My name is FtZzy !"
On voit donc qu'appliquer la fonction sur la chaine ne la change pas, les strings sont donc bel et bien immuables. C'est une routine intéressante et presque indispensable à faire à chaque fois. Ça vous évitera d'aller sur internet un bon nombre de fois. Je ne m'attarde pas plus sur les chaines de caractères car nous aurons l'occasion de les revoir plus tard. Passons plutôt à un autre type souvent utilisé: les listes.
Listes
Parlons donc un peu des listes, si souvent utilisé dans tous les langages! Nous commencerons par voir comment créer une liste et récupérer ses valeurs.
>>> # Ceci est un commentaire >>> # Création des listes >>> my_list = [] # liste vide >>> my_list = [4] # liste avec la valeur 4 >>> my_list = ['toto', 4, []] # liste avec plusieurs valeurs de plusieurs types >>> my_list = list(('toto', 4, [])) # équivalent >>> my_list = range(5) # [0, 1, 2, 3, 4] >>> my_list = range(1, 5) # [1, 2, 3, 4] >>> my_list = range(1, 14, 2) # [1, 3, 5, 7, 9, 11, 13] >>> # Parcours d'une liste >>> len(my_list) # Longueur de la liste 7 >>> my_list[0] # Récupère la première valeur 1 >>> my_list[2] # Récupère la troisième valeur 5 >>> my_list[-1] # Récupère la dernière valeur 13 >>> my_list[-7] # Récupère la première valeur 1 >>> my_list[2:6] # Sous-liste [5, 7, 9, 11] >>> my_list[3::3] # Autre sous-liste [7, 13] >>> "c" in my_list # Check si la valeur est dans la liste False >>> 9 in my_list True
Maintenant que vous connaissez la base de la base on va voir un autre petit truc sur les listes...
>>> my_list = [] >>> dir(my_list) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] >>> help(my_list.append) L.append(object) -- append object to end >>> my_list.append(1) >>> my_list [1] >>> # my_list a changé de valeur: les listes sont donc muables ! >>> second_list = my_list >>> my_list.insert(0, "0 indique la 1e case") >>> my_list ['0 indique la 1e case', 1] >>> second_list ['0 indique la 1e case', 1] >>> second_list.pop() 1 >>> my_list ['0 indique la 1e case'] >>> second_list ['0 indique la 1e case']
Oulala, que s'est-il passé? Je n'ai modifié que
my_list mais second_list l'a aussi été... Et
bien c'est normal! Lors de la déclaration d'une variable il réserve un
espace dans la mémoire et on peut récupérer cette valeur via la fonction
id(), dans mon cas id(my_list) vaut
139812943134088, tout comme id(second_list).
C'est parce que l'opérateur = ne fait rien d'autre que créer
une référence au même objet, d'où le même id: c'est une shallow copy.
Afin de comparer deux objets nous avons le mot clé is qui
regarde les id, contrairement à == qui compare les valeurs. On
en reparlera un peu plus loin dans cette leçon.
Si vous souhaitez créer un objet totalement indépendant vous pouvez utiliser
le constructeur third_list = list(my_list). Les identifiants
sont maintenant différents. Poussons le problème encore plus loin: et si
une liste contient d'autres listes? Et bien on va tester!
>>> first_big_list = [[0, 1], ['a', 'b']] >>> second_big_list = list(first_big_list) >>> second_big_list is first_big_list # 2 objets différents False >>> first_big_list[0] = "Hey" >>> first_big_list ['Hey', ['a', 'b']] >>> second_big_list [[0, 1], ['a', 'b']] >>> # Normal jusqu'à maintenant... >>> first_big_list[1][0] = "ici" >>> first_big_list ['Hey', ['ici', 'b']] >>> second_big_list [[0, 1], ['ici', 'b']]
Et bien le constructeur de liste effectue une copie de
la liste de et ses valeurs. Cependant ces valeurs sont elles-mêmes des
listes. Globalement list() donne un id différent aux 'big_lists',
or elles se réfèrent toutes les deux à d'autres listes qui ont le même id.
C'est pourquoi modifier une des sous-listes dans l'un la modifie aussi dans
l'autre! Afin de faire la copie espérée récursivement on utilise une deep
copy, que je vous propose de le revoir lors d'un prochain cours sur les
collections et les import. En attendant tout est bien expliqué
sur stackoverflow.
Booléens
Pour finir avec les types d'aujourd'hui on va parler des
booléens. Les booléens sont des variables qui ne peuvent prendre seulement
que deux valeurs: True (vrai) ou False (faux). Il s'agit d'une particularité
de Python. Effectivement dans ce lanagage tout est VRAI sauf 0, False,
None (objet nul) et les conteneur vide (exemples: [], "", {}, ...)
grâce à la fonction __nonzero__. Nous pouvons donc écrire les
choses suivantes, que nous aurons la chance de revoir.
>>> if []: . . . . . . print("Jamais affiché") . . . elif "a": . . . . . . print("Yeah !") Yeah !
Norme de syntaxe
Je finirai ce petit cours (déjà bien rempli) avec les
normes de langage. Ce que je n'ai pas dit c'est que Python est un langage
communautaire et afin que tout le monde puisse facilement s'approprier le
code des autres ils ont défini des normes d'écriture: PEP8. Bien entendu
si vous ne les suivez pas votre programme fonctionnera mais c'est une bonne
pratique de s'y habituer dès le début. Vous pouvez ajouter une vérification
sur votre éditeur de code facilement, ou les apprendre par coeur
ici ;). Après il existe également la
commande
$ autopep8 qui permet de transformer un fichier afin de le rendre
PEP8. Je ne ferai pas la liste des bonnes manières mais je vous laisse y jeter
un œil.
Résumé
Aller on fait une petite liste des choses abordées et si ça ne vous dit
rien alors revenez dessus! Python est donc un langage interprété qui nous
avons utilisé avec bpython. Il bénéficie d'un typage fort et dynamique. Dans
ce langage tout est objet, certains sont muables et d'autres non. Nous avons vu
les fonctions dir() et help() qui nous ont aidés
à découvrir les strings et les listes. On a vu avec cette dernières les différences
de copies. Enfin on a fini avec les booléens, un outil dont vous ne soupçonnés pas
encore le pouvoir, et PEP8.
Ça vous a plu? Regarder la suite.
Cours suivant