PEP 8 – Style Guide for Python Code


Introduction

Ce document donne des conventions de "codage" en Python.

Ce document n'est qu'un extrait du document officiel complet et en Anglais.

Présentation du code

Indentation

Utiliser 4 espaces par niveau d'indentation.

# Correct:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

# Hanging indents should add a level.
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)
# Wrong:

# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# Further indentation required as indentation is not distinguishable.
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

La règle des 4 espaces est optionnelle si l'instruction s'étend sur plusieurs lignes.

Optionnel:

# Hanging indents *may* be indented to other than 4 spaces.
foo = long_function_name(
  var_one, var_two,
  var_three, var_four)

La parenthèse/accolade/crochet fermante des constructions sur plusieurs lignes peut au choix s'aligner sur le 1er caractère (non blanc) de la dernière ligne, comme dans :

my_list = [
    1, 2, 3,
    4, 5, 6,
    ]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )

ou bien s'aligner sous le 1er caractère de la ligne qui a commencé l'instruction multiligne, comme dans :

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

Tabulations ou espaces ?

Les espaces sont préférés.

Les tabulations ne doivent être utilisées que si l'ensemble du code les utilise.

En aucun cas, on ne mélange tabulations et espaces.

Imports

  • Les imports devraient être sur des lignes séparés :
    # Correct:
    import os
    import sys
    
    # Wrong:
    import sys, os
    

    Cependant, on tolère ceci :

    # Correct:
    from subprocess import Popen, PIPE
    
  • Les imports se font au début du code.

    Ils doivent être groupés selon l'ordre suivant :

    1. Import de la Standard library.
    2. Imports des Related third party.
    3. Imports des Local application/library specific.
  • Les imports avec "Wildcard" [le caractère *] (from <module> import *) devraient être évités, car cela risque de perturber l'espace de nommage.

Guillemets (quotes) des chaînes de caractères

En Python, les simples ou doubles guillemets sont équivalents pour les chaînes de caractères. Cette PEP n'émet aucune recommandation à ce sujet. Choisissez une règle, et n'en changez pas.

Pour les chaînes à triples guillemets (ex : docstring), utilisez toujours les guillemets doubles.

Espaces dans les expressions et déclarations

Manies agaçantes

Évitez les espaces supplémentaires dans les situations suivantes :

  • Immédiatement entre parenthèses, accolades ou crochets :
    # Correct:
    spam(ham[1], {eggs: 2})
    
    # Wrong:
    spam( ham[ 1 ], { eggs: 2 } )
    
  • Entre une virgule terminale et une parenthèse fermante:
    # Correct:
    foo = (0,)
    
    # Wrong:
    bar = (0, )
    
  • Immédiatement avant une virgule, un point-virgule ou deux-points :
    # Correct:
    if x == 4: print(x, y); x, y = y, x
    
    # Wrong:
    if x == 4 : print(x , y) ; x , y = y , x
    
  • Cependant, dans une tranche (slice) les deux-points se comportent comme un opérateur binaire, et devraient avoir le même espacement avant et après. Exception : quand un paramètre de tranche est omis, l'espace est omis :
    # Correct:
    ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
    ham[lower:upper], ham[lower:upper:], ham[lower::step]
    ham[lower+offset : upper+offset]
    ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
    ham[lower + offset : upper + offset]
    
    # Wrong:
    ham[lower + offset:upper + offset]
    ham[1: 9], ham[1 :9], ham[1:9 :3]
    ham[lower : : step]
    ham[ : upper]
    
  • Immédiatement avant la parenthèse ouvrante d'une liste d'arguments d'un appel de fonction :
    # Correct:
    spam(1)
    
    # Wrong:
    spam (1)
    
  • Immédiatement avant la parenthèse ouvrante d'un indice ou d'une tranche :
    # Correct:
    dct['key'] = lst[index]
    
    # Wrong:
    dct ['key'] = lst [index]
    
  • Plus d'un espace autour de l'opérateur d'affectation pour s'aligner avec un autre :
    # Correct:
    x = 1
    y = 2
    long_variable = 3
    
    # Wrong:
    x             = 1
    y             = 2
    long_variable = 3
    

Autres recommandations

  • Évitez partout les espaces trainant (en fin de ligne).
  • Entourez toujours ces opérateurs binaires d'un espace : affectation (=), incrémentation (+=, -= etc.), comparaisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), booléens (and, or, not).
  • Si des opérateurs avec differentes prioritiés sont utilisés, on peut ajouter un espace autour des opérateurs avec la(les) plus basse(s) priorité(s). Faites selon votre jugement ; cependant, n'utilisez jamais plus d'un espace, avec toujours le même espace autour d'un opérateur binaire :
    # Correct:
    i = i + 1
    submitted += 1
    x = x*2 - 1
    hypot2 = x*x + y*y
    c = (a+b) * (a-b)
    
    # Wrong:
    i=i+1
    submitted +=1
    x = x * 2 - 1
    hypot2 = x * x + y * y
    c = (a + b) * (a - b)
    
  • Pas d'espace autour du signe égal = quand il est utilisé pour désigner un argument de fonction :
    # Correct:
    def complex(real, imag=0.0):
        return magic(r=real, i=imag)
    
    # Wrong:
    def complex(real, imag = 0.0):
        return magic(r = real, i = imag)
    

Commentaires

Les commentaires qui contredisent le code sont pires qu'aucun commentaire. Faites une priorité de mettre à jour les commentaires lorsuqe le code change !

Les comments doivent être des phrases compètes. Le 1er mmot commence par une majuscule (sauf si c'est un identifiant).

Les commentaires en bloc sont un ou plusieurs paragraphes construits avec des phrases complètes, terminant par un point.

Progammeurs Python de pays non anglophones : svp écrivez vos commentaires en Anglais, à moins que vous soyez certains à 120% que le code ne sera pas lu par quelqu'un qui ne parle pas votre langue.

Commentaires en bloc

Les commentaires en bloc s'appliquent en général à tout ou partie du code qui les suit, et sont indentés comme ce code. Chaque ligne du bloc commence avec # et un simple espace.

Les paragraphes du bloc sont séparés par une ligne conentant uniquement #.

Commentaires en ligne

Utilisez les commentaires en ligne avec parcimonie.

Un commentaire en ligne est sur la même ligne qu'une déclaration. Les commentaires en ligne doivent être séparés par au moins deux espaces de la déclaration. Ils commencent avec # et un simple espace.

Les commentaires en ligne sont inutiles et perturbants s'ils déclarent des évidences. Ne faites pas ceci :

x = x + 1                 # Increment x

Mais parfois, c'est utile :

x = x + 1                 # Compensate for border

Chaînes de Documentation (docstring)

Les conventions pour écrire de bonnes docstring sont décrites dans la PEP 257.

  • Écrivez une docstrings pour chaque fonction, classe, ou methodes publiques. Le commentaire de docstring doit commencer après la lignedef.
  • La PEP 257 décrit les bonnes conventions. Retenons que le plus important est que les """ qui terminent une docstring multiligne doivent être sur une ligne séparée :
    """Return a foobang
    
    Optional plotz says to frobnicate the bizbaz first.
    """
    
  • Pour les docstrings sur une seule ligne, conservez les """ fermants sur la même ligne :
    """Return an ex-parrot."""
    

Conventions de nommage

Principe primordial

Les noms choisis doivent traduire l'usage plutôt que l'implémentation.

Descriptive: Naming Styles

Il y a de nombreux styles de nommage. Il est pratique de reconnaître ces styles, indépendamment de ce pour quoi ils sont utilisés.

Les styles de nommage suivants sont couramment distingués :

  • b (single lowercase letter)
  • B (single uppercase letter)
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords (ou CamelCase – ainsi nommmé à cause de l'allure bosselée de ses lettres).

  • mixedCase (diffère du CapitalizedWords par la minuscule de la 1ère lettre)
  • Capitalized_Words_With_Underscores (affreux !)

Par ailleurs, l'usage d'underscore (simple ou double) en début ou fin de nom correspondent à des usages particuliers (comme par exemple) :

  • single_trailing_underscore_: utilisés pour éviter les conflts de noms avec les mots-clefs de Python, ex. :
    tkinter.Toplevel(master, class_='ClassName')
    
  • __double_leading_and_trailing_underscore__: objets “magiques” ou attributs cachés. Ex. __init__, __import__ ou __file__.

Prescriptions sur les conventions de nommage

Noms à éviter

Ne jamais utiliséer seul le caractère ‘l’ (lowercase letter el), ou ‘O’ (uppercase letter oh), ou ‘I’ (uppercase letter eye) comme nom de variable. Avec certaines polices, ces caractères sont confondus avec les chiffres 1 ou 0.

Compatibilité ASCII

Les identifiants choisis doivent être compatibles avec l'encodage ASCII.

Noms de Classes

Les noms de classes doivent suivre la convention CapWords.

Noms des fonctions et variables

Les noms de fonctions sont en minuscules, avec les mmots séparés par des underscore.

Les noms de variables suivent ces mêmes conventions.

Paramètres des fonctions et méthodes

Toujours utiliser self pour le 1er paramètre des méthodes d'instance.

Toujours utiliser cls pour le 1er paramètre des méthodes de classe.

Constantes

Les constantes sont générallement écrites en lettres capitales avec des underscore entre les mots. Ex : MAX_OVERFLOW ou TOTAL.

Recommandations de programmation

  • Les comparaisons à des singletons comme None doivent être faites avec is ou is not, jamais avec l'opérateur d'égalité.
  • Utilisez is not plutôt que not ... is. Bien que les deux soient fonctionnellement identiques, la 1ère façon est plus lisible et préférée :
    # Correct:
    if foo is not None:
    
    # Wrong:
    if not foo is None:
    
  • Soyez consistants dans les déclarations return. Soit toutes les déclarations return renvoient une expression, ou alors aucune. Si une déclaration return renvoie une expression, alors toute déclaration return où aucune valeur n'est renvoyée doit explicitement indiquer return None, et une déclaration return explicite doit être présente à la fin de la fonction :
    # Correct:
    
    def foo(x):
        if x >= 0:
            return math.sqrt(x)
        else:
            return None
    
    def bar(x):
        if x < 0:
            return None
        return math.sqrt(x)
    
    # Wrong:
    
    def foo(x):
        if x >= 0:
            return math.sqrt(x)
    
    def bar(x):
        if x < 0:
            return
        return math.sqrt(x)
    
  • Utilisez ''.startswith() et ''.endswith() au lieu d'un "slicing" pour contôler un préfixe ou un suffixe.

    startswith() et endswith() sont plus propres et moins sujets aux erreurs :

    # Correct:
    if foo.startswith('bar'):
    
    # Wrong:
    if foo[:3] == 'bar':
    
  • Les comparaisons de type d'un objet doivent être faites avec la fonction isinstance() au lieu de comparer les types directement :
    # Correct:
    if isinstance(obj, int):
    
    # Wrong:
    if type(obj) is type(1):
    
  • Ne comparez les valeurs booléenes à True ou False en utilisant ==:
    # Correct:
    if greeting:
    
    # Wrong:
    if greeting == True:
    

    Pire:

    # Wrong:
    if greeting is True: