Source

pep8-talk / slides.md

Les 10 commandements de la PEP8


PEP?

  • Python Extension Proposal
  • Revue, discutée, approuvée, intégrée
  • ... ou rejetée

PEP

.fx: full dark

Moïse


PEP8

  • Homogénéïté de la bibliothèque standard
  • Lisibilité
  • Bonne pratique qui se propage
  • "ne pas me faire réfléchir"

.fx: full dark

Entropy


PEP8: Si tu ne le fais pas pour les autres, fais-le pour toi


PEP 20


"beautiful is better than ugly"


"readability counts"


"in the face of ambiguity, refuse the temptation to guess"


"there should be one-- and preferably only one --obvious way to do it"


PEP8

  • Code layout
  • Imports
  • Whitespace in expressions and statements
  • Comments
  • Documentation strings
  • Version bookkeeping
  • Naming conventions
  • Programming recommendations

[SPOILER ALERT!!!]


Spoiler

!sh
$ sudo pip install pep8
$ sudo pip install --upgrade pep8

Si on n'a pas "pip"

!sh
$ sudo easy_install pep8

Si on est sous Ubuntu/Debian

!sh
$ sudo apt-get install pep8

Spoiler

!sh
$ pep8 optparse.py
optparse.py:69:11: E401 multiple imports on one line
optparse.py:77:1: E302 expected 2 blank lines, found 1
optparse.py:88:5: E301 expected 1 blank line, found 0
optparse.py:222:34: W602 deprecated form of raising exception
optparse.py:347:31: E211 whitespace before '('
optparse.py:357:17: E201 whitespace after '{'
optparse.py:472:29: E221 multiple spaces before operator
optparse.py:544:21: W601 .has_key() is deprecated, use 'in'

Spoiler encore plus méchant


pylint


Retour à la PEP8


Code layout


L'indentation, bon sang!

.fx: full

indentation


Indentation : 4 espaces


Tabulations ?


Tabulations c'est "ok"

... mais :

  • ne pas mixer les tabulations et les espaces
  • privilégier les espaces, quand même.

Pourquoi ?


Indentation

  • huit espaces, c'est trop (8x1, 8x2, 8x3, 8x4...)
  • deux, c'est trop peu

Code layout

Lignes

  • Limite : 80 caractères - enfin 79...
  • Retours chariots pas n'importe où, quand même...

Code Layout

Lignes

  • Limite : 80 caractères
  • Indentation de 4 espaces

... tu vois le rapport ?


Code layout

Lignes

!python
class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if width == 0 and height == 0 and \
           color == 'red' and emphasis == 'strong' or \
           highlight > 100:
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

Code layout

Espacements

  • Deux lignes vides entre éléments 'top-niveau' (classes)
  • Une ligne entre les éléments 'internes' (méthodes)

Pourquoi ?


Espacement == Ergonomie


Code Layout

Encodage

!python
#!/usr/bin/env python
#-*- coding: utf-8 -*-

... mais on peut utiliser Latin-1, ou win-1252 ou... nawak.


Code Layout

Encodage

  • Python core => Latin-1
  • Python 3.x => utf-8

Code Layout

Encodage

  • Noms de variables,
  • de fonctions,
  • de constantes,
  • de méthodes,
  • de propriétés,
  • de classes...

EN ASCII UNIQUEMENT !


Imports


Imports

  • Au début du script
  • Après les commentaires / docstrings

Imports

NON

.fx: no

!python
import sys, os

Imports

ÇA C'EST OUI

.fx: yes

!python
import sys
import os

Imports

AH OUI ÇA OUI ÇA AUSSI

.fx: yes

!python
from subprocess import Popen, PIPE

Imports

Ordre

  1. Bibliothèque Standard
  2. Bibliothèque(s) tierce(s)
  3. Imports locaux / spécifiques

... et une ligne blanche entre les groupes d'import


Imports

.fx: yes

!python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#  Copyright 2010 Bruno Bord
#
#  Licensed under the WTFPL, Version 2
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
# 0. You just DO WHAT THE FUCK YOU WANT TO.

"""A very simple XMPP bot.

This bot responds to simple commands. You may want to send a "help"
message in order to get the list of the available commands.

"""

import logging
import os

import xmpp
from xmpp.protocol import Message

from xmppbot import Bot, ConnectionError

Imports relatifs très déconseillés


Imports

Objectifs

  • Portabilité
  • Le moins d'ambiguïté possible
  • Lisibilité (encore, hé oui...)

Imports

Imports de classe intra-module

On peut faire :

!python
from maclasse import MaClasse
from truc.chose.taclasse import TaClasse

En cas de "clash" :

!python
import maclasse
import truc.chose.taclasse

Pour utiliser :

!python
mon_objet = maclasse.MaClasse()
ton_autre_objet = truc.chose.taclasse.TaClasse()

Espaces dans les expressions


Règle : éviter les espaces superflus


Espaces dans les expressions

Parenthèses

ça c'est non

.fx: no

!python
spam( ham[ 1 ], { eggs: 2 } )
dict ['key'] = list [index]

Espaces dans les expressions

Parenthèses

ça c'est oui

.fx: yes

!python
spam(ham[1], {eggs: 2})
dict['key'] = list[index]

Espaces dans les expressions

Virgules et points-virgules

ça c'est non

.fx: no

!python
if x == 4 : print x , y ; x , y = y , x

Espaces dans les expressions

Virgules et points-virgules

un espace après

.fx: yes

!python
if x == 4: print x, y; x, y = y, x

Espaces dans les expressions

Y'a des gens qui passent des heures à faire ça

.fx: no

!python
x             = 1
y             = 2
long_variable = "quelle perte de temps!"

Chaque fois qu'un codeur perd du temps à faire ça, $DIVINITE tue un petit chat


Voulez-vous me sauver la vie ?

.fx: full dark

Kitten


Espaces dans les expressions

Restons sérieux

.fx: yes

!python
x = 1
y = 2
long_variable = "quel gain de temps"

Espaces dans les expressions

Les opérateurs

ça c'est non

.fx: no

!python
i=i+1
submitted +=1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

Espaces dans les expressions

Les opérateurs

ça c'est oui

.fx: yes

!python
i = i + 1
submitted += 1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

Espaces dans les expressions

Définitions et appels de fonction

ça c'est non

.fx: no

!python
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

Espaces dans les expressions

Définitions et appels de fonction

ça c'est oui

.fx: yes

!python
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

Une expression par ligne


Une expression par ligne

Pas encouragé

.fx: no

!python
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()

Une expression par ligne

Plutôt mieux

.fx: yes

!python
if foo == 'blah':
    do_blah_thing()
do_one()
do_two()
do_three()

Commentaires


.fx: full

Commentaires


Commentaires

  • des phrases, complètes
  • cohérentes avec le code (ne pas embrouiller les gens)
  • en anglais

Commentaires

En anglais ?

Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don't speak your language.


Commentaires

  • Même indentation que le code qui les concerne
  • un "#" suivi d'un espace (sauf indentation dans le commentaire)
  • paragraphes séparés par un espace

Commentaires

Commentaires sur la même ligne

  • séparé par deux espaces après le code
  • éviter d'enfoncer les portes ouvertes

Commentaires

!python
x = x + 1  # incrémente x
# mouais...
x = x + 1  # rajoute une marge
# mieux

Docstrings


O-bli-ga-toi-res


Où ça ?


Par-tout


Partout

.fx: full dark

galaxie


Docstrings

Obligatoires

  • tous les modules publics
  • toutes les fonctions
  • toutes les classes
  • toutes les méthodes de ces classes

Docstrings

Optionnelles

  • méthodes non-publiques
  • compenser par un commentaire après le def

Docstrings

Référence : PEP257

!python
def get_foobang(plotz=None):
    """Return a foobang

    Optional plotz says to frobnicate the bizbaz first.

    """

Version Bookkeeping

!python
__version__ = "$Revision: 84354 $"
# $Source$

utile pour Subversion, CVS, RCS...


Conventions de nommage


.fx: full

conventions


Conventions de nommage

Plusieurs styles existants

  • b (une seule minuscule)
  • B (une seule majuscule)
  • minuscule
  • minuscules_avec_des_underscores
  • MAJUSCULE
  • MAJUSCULES_AVEC_DES_UNDERSCORES
  • MotsEnMajuscule (appelé souvent CamelCase)
  • motAvecCapitalisationMelangee (minuscule au premier mot)
  • Mots_En_Majuscule_Avec_Des_Underscores (berk !)

Conventions de nommage

  • modules : nom court, tout en minuscules. underscores si nécessaire
  • paquetages : nom court, tout en minuscules. underscore très déconseillé

.notes: noms de fichiers, répertoires, respect de la casse


Conventions de nommage

  • classes : NomDeClasseCorrect
  • exceptions : IncorrectClassNameError (suffixe "Error" !)
  • fonctions : get_correct_number()
  • méthodes : get_correct_number(self)
  • arguments des méthodes et fonctions : get_correct_number(random=False)
  • variables : number = my_object.get_correct_number()
  • constantes : ANSWER_TO_LIFE_UNIVERSE = 42

Conventions de nommage

Public / privé

  • __mon_nom ==> "privé"
  • _mon_autre_nom ==> "protégé"

Évidemment, en Python...

  • rien n'est réellement privé
  • ce ne sont "que" des conventions

Recommendations de codage


Recommendations de codage

Ne pas désavantager les implémentations de Python

  • PyPy
  • Jython
  • IronPython
  • Pyrex
  • Psyco

Recommendations de codage

Comparaisons avec None

!python
x = None
if x:
    print "on ne passe pas ici"
else:
    print "on passera"

Recommendations de codage

Comparaisons avec None

!python
x = ""
if x:
    print "on ne passe pas ici"
else:
    print "on passera"

Recommendations de codage

Comparaisons avec None

!python
x = None
if x is None:
    print "on passera ici"
else:
    print "mais jamais ici"

Recommendations de codage

Cas spécial : les listes, tuples, chaînes

Une liste vide est False. Plus performant que len()

!python
my_list = []
if not my_list:
    print "hello les gens"

Recommendations de codage

Cas spécial : les booléens

!python
if greetings:
    print "good"

if greetins == True:
    print "not good"

if greetings is True:
    print "argh! even worse!"

Recommendations de codage

Exceptions

.fx: no

!python
class MessageError(Exception):
    pass

raise MessageError, "Ouch! Here is my message!"

.notes: deux fautes - chaîne et docstring


Recommendations de codage

Exceptions

.fx: yes

!python
class MessageError(Exception):
    """Base class for errors in the email package."""
    pass

raise MessageError("Ouch! Here is my message!")

Recommendations de codage

Exceptions

le "catch" doit être si possible spécifique

.fx: yes

!python
try:
    import platform_specific_module
except ImportError:
    platform_specific_module = None

Chaînes


méthodes de chaîne plutôt que le module string


Recommendations de codage

Chaînes

endswith ou startswith plutôt que le découpage des chaînes

!python
if foo.startswith('bar'):
    print "good"

if foo[:3] == 'bar':
    print "not good"

Hyperliens


Crédits

Présentation réalisée avec l'aide de Landslide, Scribes, déposée sous contrat Creative Commons CC-BY-SA.

Images

  • Moses : http://www.flickr.com/photos/pasukaru76/3992935923/
  • Ragdoll Kitten : http://www.flickr.com/photos/pierrickblons/4496055947/
  • Petites bédés : Oliver Widder http://geekandpoke.typepad.com/ (sous Contrat CC-BY-ND)
  • "Hubble Snaps Heavyweight of the Leo Triplet" NASA Goddard Photo and Video http://www.flickr.com/photos/gsfc/4504910807/ (sous contrat CC-BY)