• Aucun résultat trouvé

1 >>> import message2 2 Bonjour Joe

Ceci n’est pas le comportement voulu pour un module car on n’attend pas d’affichage particulier (par exemple la com-mandeimport math n’affiche rien dans l’interpréteur).

Afin de pouvoir utiliser un code Python en tant que module ou en tant que script, nous vous conseillons la structure suivante :

1 """ Script de test .""" 2

3

4 def bonjour ( nom ): 5 """ Dit Bonjour .""" 6 return " Bonjour " + nom 7

8

9 if __name__ == " __main__ ": 10 print ( bonjour (" Joe "))

À la ligne 9, l’instructionif __name__ == "__main__": indique à Python :

— Si le programmemessage2.py est exécuté en tant que script dans un shell, le résultat du test if sera alors True et le bloc d’instructions correspondant (ligne 10) sera exécuté :

1 $ python message2 .py 2 Bonjour Joe

— Si le programme message2.py est importé en tant que module, le résultat du test if sera alors False (et le bloc d’instructions correspondant ne sera pas exécuté) :

1 >>> import message2 2 >>>

À nouveau, ce comportement est possible grâce à la gestion des espaces de noms par Python (pour plus détails, consultez le chapitre 19 Avoir la classe avec les objets).

Au delà de la commodité de pouvoir utiliser votre script en tant que programme ou en tant que module, cela présente l’avantage de bien voir où se situe le programme principal quand on lit le code. Ainsi, plus besoin d’ajouter un commentaire # programme principal comme nous vous l’avions suggéré dans les chapitres 9 Fonctions et 12 Plus sur les fonctions. L’utilisation de la ligneif __name__ == "__main__": est une bonne pratique que nous vous recommandons!

14.7 Exercice

14.7.1 Module ADN

Dans le scriptadn.py, construisez un module qui va contenir les fonctions et constantes suivantes.

— Fonction lit_fasta() : prend en argument un nom de fichier sous forme d’une chaîne de caractères et renvoie la séquence d’ADN lue dans le fichier sous forme d’une chaîne de caractères.

— Fonction seq_alea() : prend en argument une taille de séquence sous forme d’un entier et renvoie une séquence aléatoire d’ADN de la taille correspondante sous forme d’une chaîne de caractères.

— Fonctioncomp_inv() : prend en argument une séquence d’ADN sous forme d’une chaîne de caractères et renvoie la séquence complémentaire inverse (aussi sous forme d’une chaîne de caractères).

— Fonctionprop_gc() : prend en argument une séquence d’ADN sous forme d’une chaîne de caractères et renvoie la proportion en GC de la séquence sous forme d’un float. Nous vous rappelons que la proportion de GC s’obtient comme la somme des bases Guanine (G) et Cytosine (C) divisée par le nombre total de bases (A, T, C, G).

— ConstanteBASE_COMP : dictionnaire qui contient la complémentarité des bases d’ADN (A→T, T→C, G→C et C→G). Ce dictionnaire sera utilisé par la fonctioncomp_inv().

À la fin de votre script, proposez des exemples d’utilisation des fonctions que vous aurez créées. Ces exemples d’utilisation ne devront pas être exécutés lorsque le script est chargé comme un module.

Conseils:

— Dans cet exercice, on supposera que toutes les séquences sont manipulées comme des chaînes de caractères en majus-cules.

— Pour les fonctions seq_alea() et comp_inv(), n’hésitez pas à jeter un œil aux exercices correspondants dans le chapitre 11 Plus sur les listes.

— Voici un exemple de fichier FASTAadn.fasta2pour tester la fonctionlit_fasta().

Chapitre 15

Bonnes pratiques en programmation Python

Comme vous l’avez constaté dans tous les chapitres précédents, la syntaxe de Python est très permissive. Afin d’unifor-miser l’écriture de code en Python, la communauté des développeurs Python recommande un certain nombre de règles afin qu’un code soit lisible. Lisible par quelqu’un d’autre, mais également, et surtout, par soi-même. Essayez de relire un code que vous avez écrit « rapidement » il y a un 1 mois, 6 mois ou un an. Si le code ne fait que quelques lignes, il se peut que vous vous y retrouviez, mais s’il fait plusieurs dizaines voire centaines de lignes, vous serez perdus.

Dans ce contexte, le créateur de Python, Guido van Rossum, part d’un constat simple : « code is read much more often than it is written» (« le code est plus souvent lu qu’écrit »). Avec l’expérience, vous vous rendrez compte que cela est parfaitement vrai. Alors plus de temps à perdre, voyons en quoi consistent ces bonnes pratiques.

Plusieurs choses sont nécessaires pour écrire un code lisible : la syntaxe, l’organisation du code, le découpage en fonctions (et possiblement en classes que nous verrons dans le chapitre 19 Avoir la classe avec les objets), mais souvent, aussi, le bon sens. Pour cela, les « PEP » peuvent nous aider.

Définition

Afin d’améliorer le langage Python, la communauté qui développe Python publie régulièrement des Python Enhance-ment Proposal1(PEP), suivi d’un numéro. Il s’agit de propositions concrètes pour améliorer le code, ajouter de nouvelles fonctionnalités, mais aussi des recommandations sur la manière d’utiliser Python, bien écrire du code, etc.

On va aborder dans ce chapitre sans doute la plus célèbre des PEP, à savoir la PEP 8, qui est incontournable lorsque l’on veut écrire du code Python correctement.

Définition

On parle de code pythonique lorsque ce dernier respecte les règles d’écriture définies par la communauté Python mais aussi les règles d’usage du langage.

15.1 De la bonne syntaxe avec la PEP 8

La PEP 8 Style Guide for Python Code2est une des plus anciennes PEP (les numéros sont croissants avec le temps). Elle consiste en un nombre important de recommandations sur la syntaxe de Python. Il est vivement recommandé de lire la PEP 8 en entier au moins une fois pour avoir une bonne vue d’ensemble. On ne présentera ici qu’un rapide résumé de cette PEP 8.

15.1.1 Indentation

On a vu que l’indentation est obligatoire en Python pour séparer les blocs d’instructions. Cela vient d’un constat simple, l’indentation améliore la lisibilité d’un code. Dans la PEP 8, la recommandation pour la syntaxe de chaque niveau d’indentation est très simple : 4 espaces. N’utilisez pas autre chose, c’est le meilleur compromis.

1. https://www.python.org/dev/peps/

2. https://www.python.org/dev/peps/pep-0008/

Chapitre 15. Bonnes pratiques en programmation Python 15.1. De la bonne syntaxe avec la PEP 8

Attention

Afin de toujours utiliser cette règle des 4 espaces pour l’indentation, il est essentiel de régler correctement votre éditeur de texte. Consultez pour cela l’annexe Installation de Python disponible en ligne3. Avant d’écrire la moindre ligne de code, faites en sorte que lorsque vous pressez la touche tabulation, cela ajoute 4 espaces (et non pas un caractère tabulation).

15.1.2 Importation des modules

Comme on l’a vu au chapitre 8 Modules, le chargement d’un module se fait avec l’instructionimport module plutôt qu’avecfrom module import *.

Si on souhaite ensuite utiliser une fonction d’un module, la première syntaxe conduit àmodule.fonction() ce qui rend explicite la provenance de la fonction. Avec la seconde syntaxe, il faudrait écrirefonction() ce qui peut :

— mener à un conflit si une de vos fonctions a le même nom ;

— rendre difficile la recherche de documentation si on ne sait pas d’où vient la fonction, notamment si plusieurs modules sont chargés avec l’instruction

from module import *

Par ailleurs, la première syntaxe définit un « espace de noms » (voir chapitre 19 Avoir la classe avec les objets) spécifique au module.

Dans un script Python, on importe en général un module par ligne. D’abord les modules internes (classés par ordre alphabétique), c’est-à-dire les modules de base de Python, puis les modules externes (ceux que vous avez installés en plus).

Si le nom du module est trop long, on peut utiliser un alias. L’instructionfrom est tolérée si vous n’importez que quelques fonctions clairement identifiées.

En résumé :

1 import module_interne_1 2 import module_interne_2

3 from module_interne_3 import fonction_sp é cifique

4 from module_interne_4 import constante_1 , fonction_1 , fonction_2 5

6 import module_externe_1 7 import module_externe_2

8 import module_externe_3_qui_a_un_nom_long as mod3

15.1.3 Règles de nommage

Les noms de variables, de fonctions et de modules doivent être de la forme :

1 ma_variable

2 fonction_test_27 () 3 mon_module

c’est-à-dire en minuscules avec un caractère « souligné » (« tiret du bas » ou underscore en anglais) pour séparer les différents « mots » dans le nom.

Les constantes sont écrites en majuscules :

1 MA_CONSTANTE 2 VITESSE_LUMIERE

Les noms de classes (chapitre 19) et les exceptions (chapitre 21) sont de la forme :

1 MaClasse 2 MyException

Remarque

Le style recommandé pour nommer les variables et les fonctions en Python est appelé snake_case. Il est différent du CamelCaseutilisé pour les noms des classes et des exceptions.

Pensez à donner à vos variables des noms qui ont du sens. Évitez autant que possible lesa1, a2, i, truc, toto. . . Les noms de variables à un caractère sont néanmoins autorisés pour les boucles et les indices :

15.1. De la bonne syntaxe avec la PEP 8 Chapitre 15. Bonnes pratiques en programmation Python

1 >>> ma_liste = [1, 3, 5, 7, 9, 11] 2 >>> for i in range ( len ( ma_liste )): 3 ... print ( ma_liste [i])

Bien sûr, une écriture plus « pythonique » de l’exemple précédent permet de se débarrasser de l’indicei :

1 >>> ma_liste = [1, 3, 5, 7, 9, 11] 2 >>> for entier in ma_liste :

3 ... print ( entier ) 4 ...

Enfin, des noms de variable à une lettre peuvent être utilisés lorsque cela a un sens mathématique (par exemple, les noms x, y et z évoquent des coordonnées cartésiennes).

15.1.4 Gestion des espaces

La PEP 8 recommande d’entourer les opérateurs (+, -, /, *, ==, !=, >=, not, in, and, or. . . ) d’un espace avant et d’un espace après. Par exemple :

1 # code recommand é : 2 ma_variable = 3 + 7 3 mon_texte = " souris " 4 mon_texte == ma_variable 5 # code non recommand é : 6 ma_variable =3+7

7 mon_texte =" souris " 8 mon_texte == ma_variable

Il n’y a, par contre, pas d’espace à l’intérieur de crochets, d’accolades et de parenthèses :

1 # code recommand é : 2 ma_liste [1]

3 mon_dico {" clé"} 4 ma_fonction ( argument ) 5 # code non recommand é : 6 ma_liste [ 1 ]

7 mon_dico {" clé" }

8 ma_fonction ( argument )

Ni juste avant la parenthèse ouvrante d’une fonction ou le crochet ouvrant d’une liste ou d’un dictionnaire :

1 # code recommand é : 2 ma_liste [1]

3 mon_dico {" clé"} 4 ma_fonction ( argument ) 5 # code non recommand é : 6 ma_liste [1]

7 mon_dico {" clé"} 8 ma_fonction ( argument )

On met un espace après les caractères: et , (mais pas avant) :

1 # code recommand é : 2 ma_liste = [1, 2, 3]

3 mon_dico = {" clé 1": " valeur1 ", "clé 2": " valeur2 "} 4 ma_fonction ( argument1 , argument2 )

5 # code non recommand é : 6 ma_liste = [1 , 2 ,3]

7 mon_dico = {" clé 1":" valeur1 ", "clé 2":" valeur2 "} 8 ma_fonction ( argument1 , argument2 )

Par contre, pour les tranches de listes, on ne met pas d’espace autour du:

1 ma_liste = [1, 3, 5, 7, 9, 1] 2 # code recommand é :

3 ma_liste [1:3] 4 ma_liste [1:4:2] 5 ma_liste [::2]

6 # code non recommand é : 7 ma_liste [1 : 3]

8 ma_liste [1: 4:2 ] 9 ma_liste [ : :2]

Enfin, on n’ajoute pas plusieurs espaces autour du= ou des autres opérateurs pour faire joli :

1 # code recommand é : 2 x1 = 1

3 x2 = 3 4 x_old = 5

Chapitre 15. Bonnes pratiques en programmation Python 15.1. De la bonne syntaxe avec la PEP 8

5 # code non recommand é : 6 x1 = 1

7 x2 = 3 8 x_old = 5

15.1.5 Longueur de ligne

Une ligne de code ne doit pas dépasser 79 caractères, pour des raisons tant historiques que de lisibilité. On a déjà vu au chapitre 3 Affichage que le caractère\ permet de couper des lignes trop longues. Par exemple :

1 >>> ma_variable = 3

2 >>> if ma_variable > 1 and ma_variable < 10 \

3 ... and ma_variable % 2 == 1 and ma_variable % 3 == 0: 4 ... print (" ma variable vaut {}". format ( ma_variable )) 5 ...

6 ma variable vaut 3

À l’intérieur d’une parenthèse, on peut revenir à la ligne sans utiliser le caractère\. C’est particulièrement utile pour préciser les arguments d’une fonction ou d’une méthode, lors de sa création ou lors de son utilisation :

1 >>> def ma_fonction ( argument_1 , argument_2 , 2 ... argument_3 , argument_4 ): 3 ... return argument_1 + argument_2 4 ...

5 >>> ma_fonction (" texte très long ", " tigre ", 6 ... " singe ", " souris ")

7 'texte très longtigre '

Les parenthèses sont également très pratiques pour répartir sur plusieurs lignes une chaîne de caractères qui sera affichée sur une seule ligne :

1 >>> print (" ATGCGTACAGTATCGATAAC " 2 ... " ATGACTGCTACGATCGGATA " 3 ... " CGGGTAACGCCATGTACATT ")

4 ATGCGTACAGTATCGATAACATGACTGCTACGATCGGATACGGGTAACGCCATGTACATT

Notez qu’il n’y a pas d’opérateur+ pour concaténer les trois chaînes de caractères et que celles-ci ne sont pas séparées par des virgules. À partir du moment où elles sont entre parenthèses, Python les concatène automatiquement.

On peut aussi utiliser les parenthèses pour évaluer un expression trop longue :

1 >>> ma_variable = 3

2 >>> if ( ma_variable > 1 and ma_variable < 10

3 ... and ma_variable % 2 == 1 and ma_variable % 3 == 0): 4 ... print (" ma variable vaut {}". format ( ma_variable )) 5 ...

6 ma variable vaut 3

Les parenthèses sont aussi très utiles lorsqu’on a besoin d’enchaîner des méthodes les unes à la suite des autres. Un exemple se trouve dans le chapitre 17 Quelques modules d’intérêt en bioinformatique, dans la partie consacrée au module pandas.

Enfin, il est possible de créer des listes ou des dictionnaires sur plusieurs lignes, en sautant une ligne après une virgule :

1 >>> ma_liste = [1, 2, 3, 2 ... 4, 5, 6, 3 ... 7, 8, 9] 4 >>> mon_dico = {" clé 1": 13, 5 ... "clé 2": 42, 6 ... "clé 3": -10}

15.1.6 Lignes vides

Dans un script, les lignes vides sont utiles pour séparer visuellement les différentes parties du code.

Il est recommandé de laisser deux lignes vides avant la définition d’une fonction ou d’une classe et de laisser une seule ligne vide avant la définition d’une méthode (dans une classe).

On peut aussi laisser une ligne vide dans le corps d’une fonction pour séparer les sections logiques de la fonction, mais cela est à utiliser avec parcimonie.