Le PEP 8 en résumé !

Internet, c’est la culture du TL;DR[1], le PEP8 est un guide pour bien coder en Python. Ce document est long et voici donc un résumé.

Ce texte liste les règles stylistiques recommandées, invitant toute la communauté Python à écrire un code de la même façon.

D'autres éléments de style (qui ne sont pas dans le PEP8) ont été ajouté car étant listés comme des choix les plus courants.

MéthodeEspaces

Les opérateurs doivent être entourés d’espaces.

Il faut faire ceci :

1
variable = 'valeur'
2
ceci == cela
3
1 + 2

et non :

1
variable='valeur'
2
ceci==cela
3
1+2

Il y a deux exceptions notables.

La première étant qu’on groupe les opérateurs mathématiques ayant la priorité la plus haute pour distinguer les groupes :

1
a = x*2 - 1
2
b = x*x + y*y
3
c = (a+b) * (a-b)

La seconde est le signe = dans la déclaration d’arguments et le passage de paramètres :

1
def fonction(arg='valeur'): #  ça c'est ok
2
    pass
3
4
resultat = fonction(arg='valeur') #  ça aussi

On ne met pas d’espace à l’intérieur des parenthèses, crochets ou accolades.

Oui :

1
2 * (3 + 4)
2
3
def fonction(arg='valeur'):
4
5
{str(x): x for x in range(10)}
6
7
val = dico['key']

Non :

1
2 * ( 3 + 4 )
2
3
def fonction( arg='valeur' ):
4
5
{ str(x): x for x in range(10) }
6
7
val = dico[ 'key' ]

On ne met pas d’espace avant les deux points et les virgules, mais après oui.

Oui :

1
def fonction(arg1='valeur', arg2=None):
2
3
dico = {'a': 1}

Non :

1
def fonction(arg='valeur' , arg2=None) :
2
3
dico = {'a' : 1}

MéthodeLignes

Une ligne doit se limiter à 79 caractères. Cette limite, héritée des écrans tout petits, est toujours en vigueur car il est plus facile de scanner un code sur une courte colonne qu’en faisant des aller-retours constant.

Si une ligne est trop longue, il existe plusieurs manières de la raccourcir :

1
foo = la_chose_au_nom_si_long_quelle_ne_tient_pas_sur(
2
          une, 
3
          carte, 
4
          de, 
5
          munchkin)

Ici l’indentation entre le nom de la fonction et des paramètres est légèrement différente pour mettre en avant la distinction.

Une variante :

1
foo = la_chose_au_nom_si_long_quelle(ne, tient, pas, sur, carte 
2
                                     une, de, munchkin)

Si c’est un appel chaîné, on peut utiliser \ pour mettre à la ligne :

1
queryset = ModelDjangoALaNoix.objects\
2
                             .filter(banzai=True)\
3
                             .exclude(chawarma=False)

Si c’est une structure de données, on peut se la jouer langage fonctionnel :

1
chiffres = [
2
    1, 2, 3,
3
    4, 5, 6,
4
]
5
6
contacts = {
7
    'Cleo': (),
8
    'Ramses': (
9
        ('maman', '0248163264'),
10
        ('papa', '01234567890'),
11
        ('mamie', '55555555'),
12
        ('momie', '066642424269')
13
    )
14
}

Séparer les fonctions et les classes à la racine d’un module par 2 lignes vides. Les méthodes par 1 ligne vide.

Les imports de plusieurs modules doivent être sur plusieurs lignes :

1
import sys
2
import os

et non :

1
import sys, os

Bien sûr, ce n’est pas valable pour :

1
from x import z

Souvenez-vous qu’on peut utiliser les parenthèses pour diviser de longues lignes. Par exemple :

1
from minibelt import (dmerge, get, iget, normalize, 
2
                      chunks, window, skip_duplicates, flatten)

Idem pour les chaînes très longues :

1
s = ("Les chaînes Python sont automatiquement"
2
     "concaténées par la VM si elles sont "
3
     "uniquement séparées par des espaces "
4
     "ou sauts de lignes.")

Pour en revenir aux lignes d’import, on doit les ordonner ainsi :

  • Import de module > import du contenu du module

  • Import de la lib standard > import de libs tierces parties > import de votre projet

Exemple :

1
import os  # import module de la lib standard
2
import sys # on groupe car même type 
3
4
from itertools import islice  # import du contenu du module
5
from collections import namedtuple # import groupe car même type
6
7
import requests # import lib tierce partie
8
import arrow # on groupe car même type
9
10
from django.conf import settings # tierce partie, contenu du module
11
from django.shortcuts import redirect # on groupe car même type
12
13
from mon_projet.mon_module import mon_truc # mon projet

MéthodeNoms de variables

Lettres seules, en minuscule : pour les boucles et les indices.

Exemple :

1
for x in range(10):
2
    print(x)
3
4
i = get_index() + 12
5
print(ma_liste[i])

Lettres minuscules + underscores (tiret du bas _) : pour les modules, variables, fonctions et méthodes.

1
une_variable = 10
2
3
def une_fonction():
4
    return locals() or {}
5
6
class UneClasse:
7
    def une_methode_comme_une_autre(self):
8
        return globals()

Lettres majuscules + underscores : pour les (pseudo) constantes.

1
MAX_SIZE = 100000  # à mettre après les imports

Camel case : nom de classe.

1
class CeciEstUneClasse:
2
    def methodiquement(self):
3
        pass

Si le nom contient un acronyme, on fait une entorse à la règle :

1
class HTMLParserCQFDDDTCCMB:
2
    def methodiquement(self):
3
        pass

On n’utilise PAS le mixedCase.

MéthodeFormat du fichier

Indentation : 4 espaces.

Pas de tabulation. C’est tout. Ce n’est pas du PEP8, c’est juste que les codes qui utilisent les tabs sont en (très très très très très très très très) grande minorité dans la communauté Python.

Encodage : UTF-8 ou ASCII (ce qui est de l’UTF-8 de toute façon).

MéthodeDocstrings

On utilise toujours des triples quotes :

1
def fonction_avec_docstring_courte():
2
    """Résumé en une ligne."""
3
    pass

Si la docstring est longue (elle peut être très très très longue si vous le souhaitez) :

1
def fonction():
2
    """Résumé en une ligne suivi d'une line vide.
3
4
    Description longue de la fonction qui 
5
    se termine par une ligne vide puis une
6
    triple quotes sur sa propre ligne.
7
8
    """