\documentclass[10pt,hyperref={pdfpagemode=FullScreen,colorlinks=true, linktoc=section,urlcolor=red, linkcolor=black},xcolor=table]{beamer}

\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{graphicx}
\usepackage{alltt}
\usepackage{amsmath, stmaryrd}

%\usepackage[usenames,dvipsnames]{color}
%-% Définissons quelques couleurs
\definecolor{darkred}{rgb}{0.5,0,0}
\definecolor{darkgreen}{rgb}{0,0.5,0}
\definecolor{darkblue}{rgb}{0,0,0.5}

%-% Pour faire du cross-référencement
%-% Les caractères UTFs dans ces balises semblent poser des soucis
%\usepackage[colorlinks, pdftex]{hyperref}
\makeatletter
\AtBeginDocument{
  \hypersetup{
    linkcolor = blue,
    filecolor = darkgreen,
    urlcolor = blue,
    citecolor = blue,
    pdftitle = {\@title},
    pdfauthor = {\@author},
    pdfcreator  = {PDFLaTeX},
    pdfproducer = {PDFLaTeX}
    }
}
\makeatother

%-% Pour utiliser des caractères unicodes en maths et les définir (n'utilisez pas ucs)
\usepackage{newunicodechar}

\usepackage{palatino}
\setbeamercovered{transparent}
\setbeamercolor{section in head/foot}{use=structure,bg=structure.fg!25!bg}
\useoutertheme[subsection=false,footline=authortitle]{miniframes}
\setbeamertemplate{frametitle}[default][center]

% Les symboles de navigation, c'est moche
\setbeamertemplate{navigation symbols}{}

\author{Vincent \textsc{Le Gallic}}
\institute{Séminaire Technique du Cr@ns}
\date{4 février 2014}
\title[Python advanced]{Python\\niveau avancé}


% Pour la coloration syntaxique
% penser à rajouter le flag -shell-escape dans l'invocation de LaTeX
% Nécessite pygmentize (installer python-pygments)
% Attention, j'utilise la version 2.0-alpha2 de minted, qui fix les problèmes
% de non-ascii et fournit \mintinline
\usepackage{minted}

% Pour que pygments n'encadre pas en rouge moche
% les erreurs de syntaxe dans le langage coloré
\expandafter\def\csname PY@tok@err\endcsname{}

% Environnement pour colorer en python en mode in-line
\newcommand{\python}[1]{\mintinline{python}{#1}}

% Pour écrire rapidement les __fonctions__ spéciales
\newcommand{\spec}[1]{\texttt{\_\,\_{#1}\_\,\_}}

% Spoilers !
\setbeamercovered{transparent=0}

\begin{document}

\begin{frame}
 \maketitle
 \begin{center}
  \includegraphics[width=0.2\linewidth]{images/logo-python.pdf}
 \end{center}
 \begin{footnotesize}
  Ce séminaire fait suite au \href{https://wiki.crans.org/CransTechnique/CransApprentis/SeminairesTechniques/2013-2014?action=AttachFile&do=view&target=python_beginner.pdf}{séminaire Python niveau débutant}
 \end{footnotesize}
\end{frame}

\begin{frame}
 \tableofcontents
\end{frame}

\section{Modules built-in}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}

\subsection{Maths et aléa}
\begin{frame}
 \frametitle{Fonctions mathématiques}
 \python{import math}
 \begin{itemize}
  \item \python{math.log(x [,base])}, \python{math.exp(x)}
  \item \python{math.sqrt(x)}
  \item \python{math.cos(x)}, \python{math.sin(x)}, \python{math.tan(x)},
        \python{math.acos(x)}, \python{math.asin(x)}, \python{math.atan(x)}
  \item Les mêmes avec un \texttt{h} à la fin pour les hyperboliques.
  \item \python{math.degrees(r)}, \python{math.radians(d)} : convertit des radians en degrés et inversement
  \item Deux constantes : \python{math.pi}, \python{math.e}
  \item Doc complète : \begin{scriptsize}\url{http://docs.python.org/2/library/math.html}\end{scriptsize}
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Aléatoire}
 \python{import random}
 \begin{itemize}
  \item \python{random.random()} : renvoie un \python{float} aléatoire dans $[0, 1[$
  \item \python{random.randint(a ,b)} : renvoie un entier aléatoire dans $\llbracket a, b \rrbracket$
  \item \python{random.choice(l)} : choisit un élément aléatoire dans l'itérable.
  \item \python{random.randrange(start, stop, step)} équivalent à \python{random.choice(random.randrange(start, stop, step))}
  (\python{start} et \python{step} sont facultatifs)
  \item \python{random.shuffle(l)} : mélange l \textit{in place}, \python{random.sample(l, k)} : donne \python{k} éléments choisis aléatoirement dans \python{l} (sans remise)
  \item \python{random.uniform(a, b)} : retourne un \python{float} tiré de manière uniforme dans $[a, b]$
  \item D'autres lois de répartition : \python{expovariate, gammavariate, gauss, normalvariate}\ldots
  \item Doc complète : \begin{scriptsize}\url{http://docs.python.org/2/library/random.html}\end{scriptsize}
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Pseudo-Aléatoire ?}
 \begin{itemize}
  \item \python{random.seed([x])} : permet d'initialiser le générateur aléatoire. Si \python{x} n'est pas fourni, le temps système sera utilisé. (Ce seed est effectué à l'import du module.)
  \item \python{random.getstate()}, \python{random.setstate(state)} : récupère/force l'état interne du générateur aléatoire. Utile pour rejouer les mêmes séquences.
  \item Tout ceci est pseudo-aléatoire, avec une seed.
  On peut générer de l'aléatoire en utilisant \python{random.SystemRandom}, qui utilisera \python{os.urandom}, qui se sert des sources d'entropie du système d'exploitation, si disponibles.
 \end{itemize}
\end{frame}

\subsection{Temps et dates}
\begin{frame}
 \frametitle{Représentation du temps}
 \python{import time}
 \begin{itemize}
   \item \python{time.time()} : date actuelle, en secondes depuis l'Epoch\footnote{1er Janvier 1970 00h, UTC}.
  \item \python{time.localtime([seconds])} : renvoie (année, mois, jour, heure, minute, seconde, \texttt{wday}, \texttt{yday}, \texttt{isdst}) de la timezone locale où \texttt{wday} est le numéro du jour dans la semaine (lundi = 0), \texttt{yday} le numéro du jour dans l'année (de 1 à 366) et \texttt{isdst} le flag Daylight Savings Time. Si \texttt{seconds} est fournit, convertit cette durée depuis l'Epoch en 9-tuple.
  \item \python{time.gmtime([seconds])} : même chose mais en temps UTC.
  \item \python{time.mktime(9-tuple)} : convertit un 9-tuple en secondes depuis l'Epoch.
  \item \python{time.clock()} : temps CPU depuis le démarrage de l'interpréteur.
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \begin{itemize}
  \item \python{time.strftime(format[, 9-tuple])} : Renvoie la date courante (ou celle du tuple) formatée selon \texttt{format} : par exemple \verb@"%Y-%m-%d_%H:%M:%S"@ (cf \texttt{man date}).
  \item \python{time.strptime(format, string)} : Convertit la chaîne en 9-tuple en utilisant le format.
 \end{itemize}
 \python{import datetime}
 \begin{itemize}
  \item \python{datetime.date(year, month, day)} : Créer un objet date.
  \item \python{datetime(year, month, day[, hour[, minute} \python{[, second[, microsecond[, tzinfo]]]]])} : Créer un objet timestamp.
  \item \python{datetime.timedelta} : Type de la différence entre deux dates.
  \item On peut faire la différence entre deux \python{datetime}, on obtient un \python{timedelta}, type qu'on peut ajouter à un \python{datetime}.
  \item Un objet \python{datetime} a une méthode \python{.strftime(format)}
 \end{itemize}
\end{frame}

\subsection{Système}
\begin{frame}
 \frametitle{Intéraction avec le système}
 \python{import os}
 \begin{itemize}
  \item \python{os.rename(old, new)}, \python{os.renames(old, new)} : déplace le fichier/dossier. (\python{renames} crée et supprime les dossiers nécessaires.)
  \item \python{os.remove(path)}, \python{os.rmdir(path)} : supprime le fichier/le dossier si il est vide.
  \item \python{os.chdir(path)} : change le répertoire courant.
  \item \python{os.umask(mask)} : changel l'umask en octal (et renvoie le précédent).
  \item \python{os.chmod(path, mode)}, \python{os.chown(path, uid, gid)}
  \item \python{os.mkdir(path[, mode])}, \python{os.makedirs(path[, mode])} : crée le/les répertoires.
  \item \python{os.environ} : l'environnement du shell, sous forme de dictionnaire.
  \item \python{os.getcwd()} : renvoie le chemin absolu du répertoire courant.
 \end{itemize}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item \python{os.getenv(key[, default])}, \python{os.putenv(key, value)}, \python{os.unsetenv(key)} : récupère une variable d'environnement / définit ou en modifie une / en supprime une.
  \item \python{os.geteuid()}, \python{os.getgid()}, \python{os.getgroups()} : récupère l'uid, le gid principal ou tous les gid de tous les groupe de l'utilisateur courant.
  \item \python{os.getpid()} : obtenir le PID du processus actuel
  \item \python{os.fork()} : dupliquer le processus. Dans le processus fils, la valeur retournée est 0, dans le processus parent, la valeur est le PID du fils.
  \item \python{os.linesep} : contient le séparateur de ligne (\python{"\n"} sous Linux, \python{"\r\n"} sous Windows…), utile pour la portabilité.
  \item \python{os.symlink(src, dest)}, \python{os.readlink(path)} : crée un lien symbolique / lit la destination d'un lien symbolique.
 \end{itemize}
\end{frame}

\begin{frame}
 \python{import sys}
 \begin{itemize}
  \item \python{sys.argv} : La liste des paramètres fournis sur la ligne de commande (avec la commande en \python{[0]}).
  \item \python{sys.exit([status])} : Quitter (avec éventuellement un code de retour, sinon 0)
  \item \python{sys.getfilesystemencoding()} : Renvoie l'encodage utilisé par le système de fichiers.
  \item \python{sys.getrecursionlimit()}, \python{sys.setrecursionlimit(n)} : donne/modifie la profondeur d'appel maximale.
  \item \python{sys.getrefcount(objet)} : donne le nombre de référence vers cet objet python (+1 parce que la fonction elle-même y fait référence).
  \item \python{sys.maxint}, \python{sys.maxunicode} : contiennent le plus grand \python{int} et le dernier point de code unicode.
 \end{itemize}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item \python{sys.path} : la liste des dossiers dans lesquels l'interpréteur va chercher (dans l'ordre) les modules lorsqu'on fait un \python{import}. (ex : \python{sys.path.insert(0, "/meslib/prioritaires/")}, \python{sys.path.append("/usr/scripts/")}\footnote{Au Cr@ns, on préfèrera utiliser \texttt{\#!/bin/bash /usr/scripts/python.sh} qui fait cet ajout une fois pour toutes.})
  \item \python{sys.stin}, \python{sys.stdout}, \python{sys.stderr} : Les fichiers d'entrée, de sortie et d'erreur standards liés au tty en cours.
 \end{itemize}
\end{frame}

\section{Programmation Orientée objet}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}

\subsection{Introduction}
\begin{frame}
 \frametitle{La Programmation Orientée Objet : principe}
 \begin{itemize}
  \item Une \textbf{classe} est un \textit{moule} qui permet de créer plusieurs objets (des \textbf{instances}) de même type. La classe \texttt{Animal} me permet de créer l'instance \texttt{pet}:\\
   \texttt{pet = Animal(<paramètres d'initialisation>)}
  \item Les objets ont des \textbf{attributs} : \texttt{pet.taille\_queue}, \texttt{pet.cri}. Ils peuvent différer d'une instance à l'autre, et être modifiés (normalement, pas depuis l'extérieur de l'objet).
  \item Ils ont également des \textbf{méthodes}, fonctions internes à l'objet : \texttt{pet.crier()}, \texttt{pet.manger(foodsize)}.
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{La Programmation Orientée Objet : pourquoi ?}
 \begin{itemize}
  \item \textbf{Encapsulation} : la définition et le comportement d'un objet sont intérieurs à la classe, le reste du monde n'a à se soucier que de son interface.
  \item \textbf{Réutilisation du code} : un objet défini une fois peut très bien resservir tel quel dans un autre projet/script/\ldots
  \item \textbf{DRY}\footnote{"Don't Repeat Yourself", remember ? Mais vous me faites me répéter\ldots} : permet d'écrire à un seul endroit des méthodes au lieu de répéter plusieurs fois des fonctions à peine différentes.
  \item \textbf{Clarté} : \textbf{Cet} objet a \textbf{ce} comportement, \textbf{ces} méthodes. Contrairement à si je trouve une fonction seule, pour laquelle je dois me demander quels objets elle peut/doit prendre en paramètres. (adéquation sémantique/syntaxe)
 \end{itemize}
\end{frame}

\subsection{Classes}
\begin{frame}[fragile]
 \frametitle{Définition d'une classe}
 \begin{scriptsize}
 \begin{minted}[comment=NA]{python}
>>> class Chien:
        def __init__(self, poids):
            """Initialiseur"""
            # on stocke le paramètre fourni à l'initialisation dans
            # un attribut de l'objet
            self.poids = poids
        
        def crier(self):
            print "Ouaf !"
        
        def manger(self, foodsize):
            self.poids += foodsize
 \end{minted}
 \begin{minted}{pycon}
>>> medor = Chien(3)
>>> medor.poids
3
>>> medor.manger(5)
>>> medor.poids
8
>>> medor.crier()
Ouaf !
 \end{minted}
 \end{scriptsize}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item Par convention, on nomme les classes en CamlUpperCase et les méthodes en lower\_case.
  \item Les méthodes seront toujours appelées avec comme premier paramètre l'objet lui-même. Par convention, on utilise le mot "\texttt{self}", mais on pourrait utiliser autre chose (contrairement au "this" Java ou C++).
  \item Chaque méthode peut (et devrait) avoir une docstring. La docstring de la méthode \spec{init} écrasera celle de la classe.
  \item On ne devrait pas toucher aux attributs nous-même (par exemple, faire \python{pet.poids = 4}), explication slide suivante.
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Respect du privé}
 \begin{scriptsize}
 \begin{minted}{python}
>>> import math
>>> class Vecteur:
        def __init__(self, x, y):
            self.x, self.y = x, y
            self._update_norme()
        
        def __calculer_norme(self):
            return math.sqrt(self.x**2 + self.y**2)
        
        def _update_norme(self):
            self.norme = self.__calculer_norme()
        
        def setcoords(self, newx, newy):
            self.x, self.y = newx, newy
            self._update_norme()

>>> v = Vecteur(3, 4)
>>> v.norme
5.0
>>> v.x = 10
>>> v.norme
5.0
>>> v.setcoords(6, 8)
>>> v.norme
10.0
 \end{minted}
 \end{scriptsize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Plus ou moins privé}
 \begin{itemize}
 \item Les méthodes qui commencent par \texttt{\_} sont par convention privées. Mais Python permet tout de même d'y accéder :
 \begin{scriptsize}
 \begin{minted}{pycon}
>>> v.x, v.y = 9, 12
>>> v._update_norme()
>>> v.norme
15.0
 \end{minted}
 \end{scriptsize}
 
 \item Les méthodes commençant par \texttt{\_\,\_} mais qui ne finissent pas par \text{\_\,\_} sont réellement privées et donc inaccessibles :
 \begin{scriptsize}
 \begin{minted}{pycon}
>>> v.__calculer_norme()
AttributeError: Vecteur instance has no attribute '__calculer_norme'
>>> v._Vecteur__calculer_norme()
15.0
 \end{minted}
 \end{scriptsize}
 En réalité, la méthode est renommée en ajoutant \texttt{\_ClassName} au début\footnote{On appelle ce procédé le \textbf{mangling}}, elle reste \textit{quand même} accessible, mais c'est sale, ne faites pas ça.
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Un peu de cosmétique}
 \begin{itemize}
  \item Par défaut, c'est un peu moche :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> v
<__main__.Vecteur instance at 0x7fc1e42ec5a8>
>>> print v
<__main__.Vecteur instance at 0x7fc1e42ec5a8>
  \end{minted}
  \end{scriptsize}
  \item \begin{small}On peut \textbf{surcharger} les \textbf{fonctions spéciales} qui sont appelées dans ces cas-là :\end{small}
  \begin{scriptsize}
  \begin{minted}{python}
>>> class Vecteur:
        [...]
        def __str__(self):
            return "Vecteur de coordonnées (%s, %s)" % (self.x, self.y)
        
        def __repr__(self):
            return "(%s, %s)" % (self.x, self.y)
\end{minted}
\begin{minted}{pycon}
>>> v = Vecteur(3, 4)
>>> v
(3, 4)
>>> str(v)
'Vecteur de coordonn\xc3\xa9es (3, 4)'
>>> print v
Vecteur de coordonnées (3, 4)
  \end{minted}
  \end{scriptsize}
  En règle générale, il est déconseillé de surcharger \python{repr}, et fortement déconseillé de lui faire sortir du non-ASCII.
 \end{itemize}
\end{frame}

\subsection{Surcharge}
\begin{frame}[fragile]
 \frametitle{Surcharge des opérateurs}
 \begin{itemize}
  \item
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> v + v
TypeError: unsupported operand type(s) for +: 'instance' and 'instance'
  \end{minted}
  \end{scriptsize}\small
  \item Une autre fonction spéciale particulièrement utile à surcharger : \spec{add}
  \begin{scriptsize}
  \begin{minted}{python}
>>> Class Vecteur:
        [...]
        def __add__(self, v2):
            return Vecteur(self.x + v2.x, self.y + v2.y)
\end{minted}
\begin{minted}{pycon}
>>> u, v = Vecteur(1,2), Vecteur(3,4)
>>> print u + v
Vecteur de coordonnées (4, 6)
  \end{minted}
  \end{scriptsize}
  \item Le principe est toujours le même : la fonction spéciale (correspondant à l'opérateur) de l'objet de gauche est appelée avec pour paramètre l'objet de droite.
  \item On peut prévoir de prendre en paramètre un objet d'un autre type (comme \python{datetime.datetime} et \python{datetime.timedelta}).
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \begin{itemize}
  \small
  \item Autre exemple, avec \spec{eq} :
  \begin{scriptsize}
  \begin{minted}{python}
>>> class NonCaseSensitiveString:
        def __init__(self, s):
            self.s = s
        def __str__(self):
            return self.s.__str__()
        def __eq__(self, s2):
            return self.s.lower() == s2.s.lower()
\end{minted}
\begin{minted}{pycon}
>>> s = NonCaseSensitiveString("CouCou")
>>> t = NonCaseSensitiveString("coUcOu")
>>> s == t
True
  \end{minted}
  \end{scriptsize}
  \item Autres fonctions spéciales utiles à connaître :
  \vspace{-2ex}
  \begin{columns}[t]
  \begin{column}{0.5\linewidth}
   \begin{itemize}
    \item \spec{sub} : -
    \item \spec{div} : /
    \item \spec{mod} : \%
    \item \spec{mul} : *
    \item \spec{pow} : **
    \item \spec{neg} : opposé
    \item \spec{cmp} : renvoie -1 si <, 0 si ==, 1 si >
   \end{itemize}
  \end{column}
  \begin{column}{0.5\linewidth}
   \begin{itemize}
    \item \spec{nonzero} : résultat de \python{x != 0}, utilisé pour la conversion en booléen
    \item \spec{float} : \python{float(x)}
    \item \spec{int} : \python{int(x)}
    \item \spec{and}, \spec{or} : opérations logiques
   \end{itemize}
  \end{column}
 \end{columns}
 \end{itemize}
\end{frame}


\subsection{Héritage}
\begin{frame}[fragile]
 \frametitle{DRY++ : L'héritage}
 \vspace{-3ex}
 \begin{columns}[t]
 \begin{column}{0.4\linewidth}
  \small
  \begin{itemize}
   \item On peut factoriser le code en définissant la même méthode pour plusieurs classes.
   \bigskip
   \item<2-> Appeler l'initialiseur du parent n'est pas automatique (et donc pas obligatoire).
   \item<3-> On peut écraser une méthode :
   \begin{scriptsize}
   \begin{minted}{python}
>>> class Lapin(Animal):
     [...]
     def crier(self):
       raise NotImplementedError
   \end{minted}
   \end{scriptsize}
  \end{itemize}
 \end{column}
 \begin{column}{0.6\linewidth}
  \begin{itemize}
   \item
   \begin{scriptsize}
   \begin{minted}{python}
>>> class Animal:
        def __init__(self, poids):
            """Initialiseur"""
            self.poids = poids
        def crier(self):
            print "%s !" % (self.cri)
        def manger(self, foodsize):
            self.poids += foodsize

>>> class Chien(Animal):
        def __init__(self, poids):
            Animal.__init__(self, poids)
            self.cri = "Ouaf"

>>> class Chat(Animal):
        def __init__(self, poids):
            Animal.__init__(self, poids)
            self.cri = "Miaou"
\end{minted}
\begin{minted}{pycon}
>>> snoopy, felix = Chien(5), Chat(4)
>>> snoopy.manger(2)
>>> felix.manger(2)
>>> snoopy.poids, felix.poids
(7, 6)
>>> snoopy.crier(); felix.crier()
Ouaf !
Miaou !
   \end{minted}
   \end{scriptsize}
  \end{itemize}
 \end{column}
 \end{columns}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item Idéalement, on devrait faire hériter toutes les classes de \python{object}, afin qu'elles soient des new-style classes. Cela permet un certain nombre de fonctionnalités que n'ont pas les old-style classes :
  \begin{itemize}
   \item les properties
   \item les classmethod, staticmethod
   \item le support des métaclasses\footnote{pour tout ça, cf séminaire python hardcore}
  \end{itemize}
  Au départ, ces new-style classes ont été créées pour unifier classes et types : \python{type(x) == x.__class__}, ce qui n'est pas garanti pour les old-style classes. Et accessoirement, en python3, il n'y a plus que les new.
 \end{itemize}
\end{frame}

\section{Intéraction avec des fichiers}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}

\subsection{open}
\begin{frame}[fragile]
 \frametitle{Lire/Écrire dans un fichier}
 \begin{itemize}
  \item Pour écrire du texte dans un fichier :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> f = open("path/to/file", "w")
>>> f.write("Je mets des choses\ndans mon fichier")
>>> f.close()
  \end{minted}
  \end{scriptsize}
  \item Attention, il faut écrire des \python{str}, donc il faut penser à encoder avant d'éventuels \python{unicode}.
  \item Le mode \python{"w"} signifie qu'on écrase le contenu du fichier. Le mode par défaut est \python{"r"} (read), il existe également le mode \python{"a"} (append) pour écrire à la suite du fichier sans écraser ce qui y est déjà. \python{"w"} et \python{"a"} créent le fichier si il n'existait pas.
  \item Pour lire :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> f = open("path/to/file", "r")
>>> f.read()
'Je mets des choses\ndans mon fichier'
>>> f = open("path/to/file", "r")
>>> f.readlines()
['Je mets des choses\n', 'dans mon fichier']
  \end{minted}
  \end{scriptsize}
 \end{itemize}
\end{frame}

\subsection{json, pickle}
\begin{frame}[fragile]
 \frametitle{Stockage facile}
 \begin{itemize}
  \item Certains objets peuvent être sérialisés, ce sont None, les strings, nombres et les listes et dictionnaires qui en contiennent.
  \item On peut les stocker dans un fichier avec des librairies prévues à cet effet.
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> import json
>>> f = open("store.json", "w")
>>> json.dump({"a" : [3]}, f)
>>> f.close()
>>> f = open("store.json")
>>> json.load(f)
{u'a': [3]}
  \end{minted}
  \end{scriptsize}
  \item Les chaînes sont restituées sous forme d'\python{unicode} (et devrait aussi être fournis ainsi).
  \item L'objet JSON dans le fichier est à peu près human-readable.
  \item \python{pickle} est un autre module qui s'utilise de la même façon. Le format de stockage n'est pas human-readable, cependant.
 \end{itemize}
\end{frame}

\section{Bonus stuff}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}

\subsection{Nouvelle façon de voir les listes}
\begin{frame}[fragile]
 \frametitle{Listes en compréhension}
 \begin{itemize}
  \item C'est un moyen très "python-esque" de créer des listes, qui est à peu près l'équivalent d'un \python{map}.
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> l = [2, 2, 5, 10]
>>> l2 = [i**2 for i in l]
>>> l2
[4, 4, 25, 100]
  \end{minted}
  \end{scriptsize}
  \item Il est possible d'imbriquer plusieurs boucles :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> [a + b for a in "cdf" for b in "aei"]
['ca', 'ce', 'ci', 'da', 'de', 'di', 'fa', 'fe', 'fi']
  \end{minted}
  \end{scriptsize}
  \item On peut également ajouter des conditions (équivalent d'un \python{filter}) :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> [a + 1 for a in range(7) if a % 2 == 0]
[1, 3, 5, 7]
  \end{minted}
  \end{scriptsize}
  \item Ça marche aussi avec les dictionnaires\footnote{En 2.7, mais pas en 2.6} :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> {i : str(i**2) for i in range(4)}
{0: '0', 1: '1', 2: '4', 3: '9'}
  \end{minted}
  \end{scriptsize}
 \end{itemize}
\end{frame}

\subsection{argparse}
\begin{frame}[fragile]
 \frametitle{Parser les paramètres commandline}
 \begin{itemize}
 \item Code :
  \begin{scriptsize}
  \begin{minted}{python}
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse

# Déclaration du parseur (noter l'absence de u"")
parser = argparse.ArgumentParser(description="Message d'aide")
parser.add_argument("-v", "--verbose", help="Afficher plus d'infos",
                    action="store_true")
parser.add_argument("-f", "--file", help="Fichier à traiter",
                    action="store", type=str, metavar="Fi")
parser.add_argument("-n", dest="num", help="Numéro de la ligne",
                    action="store", type=int)

# Parsing
print "before parsing"
args = parser.parse_args()
print "ater parsing"

# Utilisation des arguments parsés
print "Valeurs : %r, %r, %r" % (args.verbose, args.file, args.num)
  \end{minted}
  \end{scriptsize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \begin{itemize}
  \item Exécution :
  \begin{scriptsize}
  \begin{verbatim}
vincent@eva $ ./test.py -h
before parsing
usage: test.py [-h] [-f Fi] [-n NUM]

Message d'aide

optional arguments:
  -h, --help        show this help message and exit
  -v, --verbose     Afficher plus d'infos
  -f Fi, --file Fi  Fichier à traiter
  -n NUM            Numéro de la ligne

vincent@eva $ ./test.py -v -f pif -n 6
before parsing
ater parsing
Valeurs : True, 'pif', 6

vincent@eva $ ./test.py -f pif
before parsing
ater parsing
Valeurs : False, 'pif', None

vincent@eva $ ./test.py -f pif -n
before parsing
usage: test.py [-h] [-v] [-f Fi] [-n NUM]
test.py: error: argument -n: expected one argument
  \end{verbatim}
  \end{scriptsize}
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Parser les paramètres commandline}
 \begin{itemize}
  \item Regarder la doc et les docstrings d'argparse pour voir toutes les possibilités
  \item Notamment, \python{parser.add_mutually_exclusive_group}
  \item Il existe également le module \python{optparse}, moins bien.
 \end{itemize}
\end{frame}

\subsection{re}
\begin{frame}
 \frametitle{Expressions régulières}
 \begin{itemize}
  \item Notion venant de l'info théorique, très utile et utilisée.
  \item \texttt{perl}, \texttt{sed}, \texttt{python}, \texttt{grep} en ont, mais à chaque fois avec des différences de syntaxe et d'expressivité
  \item Un peu de syntaxe des regexp :
  \begin{itemize}
   \item \python{'.'} : Tout sauf \python{'\n'}\footnote{Si DOTALL est activé, matche aussi les newline}
   \item \python{'^'}/\python{'$'} : Début/Fin de chaîne\footnote{Si MULTILINE, matche après/avant chaque newline} %$ fucking coloration syntaxique
   \item \python{'(…)'} : Délimite un groupe. Il sera accessible après et référençable dans la regexp elle-même (\python{'\1', '\2'}…)\footnote{Attention, un groupe peut exister dans d'autres cas : \python{'a|b', '[a-z]'}}.
   \item \python{'*'} : Le précédent groupe, 0 ou plus de fois.
   \item \python{'+'} : Le précédent groupe, 1 ou plus de fois.
   \item \python{'?'} : Le précédent groupe, 0 ou 1 fois.
   \item \python{'{m}', '{m,n}', '{,n}', '{m,}'} Le précédent groupe, respectivement \texttt{m} fois exactement, entre \texttt{m} et \texttt{n} fois, au plus \texttt{n} fois, au moins \texttt{m} fois.
  \end{itemize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Les regexp en python}
 \begin{itemize}
  \item Le module : \python{re}
  \item Les choses qu'on peut faire avec une regexp :
  \begin{itemize}
   \item \python{match} : vérifier que le motif matche le texte depuis son début
   \item \python{search} : trouver la première occurrence du motif dans le texte
   \item \python{findall} : trouver toutes les occurrences disjointes du motif dans le texte, renvoie une liste
   \item \python{finditer} : presque\footnote{Renvoie des match objects et non pas le résultat de \python{.groups()}} pareil, mais renvoie un itérateur
   \item \python{sub} : trouver toutes les occurrences d'une regexp et les remplacer par quelque chose (éventuellement dépendant de ce qui a exactement été matché)
  \end{itemize}
  \item Les deux façons de le faire :
  \begin{itemize}
   \item \python{re.<nom_de_la_fonction>(motif, texte)}
   \item
   \begin{minted}{python}
regexp = re.compile(motif)
regexp.<nom_de_la_fonction>(texte)
   \end{minted}
   Cette méthode permet de rajouter le paramètre \python{flags=re.UN_FLAG}
  \end{itemize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Regexp : pratique}
 \begin{itemize}
  \item Simple matching (vérifier si un truc matche une regexp) :
   \begin{scriptsize}
   \begin{minted}{pycon}
>>> import re
>>> re.match('ab+c', 'abbc')
<_sre.SRE_Match at 0x2cf9780>
>>> re.match('ab+c', 'abbcd')
<_sre.SRE_Match at 0x2cf9ac0>
>>> re.match('ab+c', 'acd')
   \end{minted}
   \end{scriptsize}
  \item Accès aux groupes :
   \begin{scriptsize}
   \begin{minted}{pycon}
>>> match = re.match('(a{2,})((b+)k)(c?)', 'aaabkd')
>>> match.group()
'aaabk'
>>> match.groups()
('aaa', 'bk', 'b', '')
   \end{minted}
   \end{scriptsize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Les escape sequences}
 Elles permettent de matcher plus de choses :
 \begin{itemize}
  \item \python{'\*'}, \python{'\?'}, \python{'\$'}… : pour matcher les caractères spéciaux (désactiver leur comportement)
  \item \python{'\1'}, …, \python{'\99'} : matche les groupes dans l'ordre
  \item \python{'\s'} : matche les whitespace, équivalent à \python{'[ \t\n\r\f\v]'} si le flag UNICODE est inactif, si il est actif, matche tout caractère espace (notamment les espaces insécables)
  \item \python{'\S'} : matche tout non-whitespace
  \item \python{'\d'} : matche tout digit, équivalent à \python{'[0-9]'}, plus si UNICODE
  \item \python{'\D'} : matche tout non-digit
  \item …
  \item Voir la \href{https://docs.python.org/2/library/re.html#regular-expression-syntax}{liste complète dans la doc}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Les flags}
 On peut modifier le comportement avec un ou plusieurs flags :
 \begin{scriptsize}
 \begin{minted}{pycon}
>>> text = "a1a\na3"
>>> r = re.compile("a.")
>>> r.findall(text)
['a1', 'a3']
>>> r = re.compile("a.", flags=re.DOTALL)
>>> r.findall(text)
['a1', 'a\n', 'a3']
 \end{minted}
 \end{scriptsize}
 \begin{itemize}
  \item DEBUG : affiche les informations sur la regexp au moment de sa compilation
  \item IGNORECASE : rend la regexp insensible à la casse
  \item MULTILINE : \python{'^'} et \python{'$'} matchent en début et fin de chaque ligne %$
  \item DOTALL : \python{'.'} matche aussi un \python{'\n'}
  \item UNICODE : change le comportement de certaines escape-sequences. Par exemple, \python{'é'} sera considéré comme un caractère alphanumérique et l'espace insécable sera matché par \python{'\s'}
 \end{itemize}
 Pour utiliser plusieurs flags, on les additionne.
\end{frame}

\begin{frame}
 \frametitle{Plus de syntaxe des regexp}
 \begin{itemize}
  \item \python{'|'} : "Ou" entre deux groupes : \python{'(aa|bb)'} matche \python{'aa'} et \python{'bb'}. Attention, \python{'aa|bb'} matche \python{'aab'} et \python{'abb'}.
  \item \python{'[…]'} : Ensemble (set) de caractères
  \begin{itemize}
   \item Un "ou++" : \python{'[abcd]'}
   \item Range : \python{'[a-zA-Z]'} (\python{'\-'} ou en début/fin de set pour un vrai tiret)
   \item Les caractères spéciaux perdent leur sens : \python{'[(+*)]'} matche un de ces caractères
   \item On peut demander le complémentaire d'un set : \python{'[^a-z]'}
   \item Pour inclure un \python{']'} dans un set, l'échapper à coup de backslash, ou le mettre au début : \python{'[a\]b]'}, \python{'[]ab]'}
  \end{itemize}
  \item Groupe spéciaux
  \begin{itemize}
   \item \python{'(?:…)'} : groupe non-capturant. Ne sera pas affiché par \python{.groups()} et ne peut pas être référencé par \python{'\1'}…
   \item \python{'(?iLmsux)'} : activer un ou des flags. C'est une alternative à la méthode consistant à les déclarer dans le \python{re.compile}.
   \item \python{'(?P<nom>…)'} : groupe capturant et nommé. On peut le référencer par son numéro ou par \python{'(?P=nom)'}. Apparaîtra dans \python{match.groupdict()}.
  \end{itemize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Quelques astuces supplémentaires}
 \begin{itemize}
  \item Application, avec \python{urllib} en bonus :
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> url = "https://wiki.crans.org/VieBde/PlanningSoirees/LeCalendrier"
>>> url += "?action=raw"
>>> texte = urllib.urlopen(url).read()
>>> regex = "(?:start|end):: (?P<date>[-0-9]+) (?P<heure>[0-9:]+)"
>>> [m.groupdict() for m in re.finditer(regex, texte)]
[{'date': '2015-03-28', 'heure': '00:00'},
 {'date': '2015-03-29', 'heure': '23:59'},
 …
 {'date': '2008-03-06', 'heure': '14:00'}]
  \end{minted}
  \end{scriptsize}
  
  \bigskip
  
  \item Attention, les multiplicateurs sont par défaut gloutons
  
  (= matchent la plus longue chaîne possible).
  
  Alternative non-gloutonne : \python{'*?', '+?', '??', '{m,n}?'}
  \begin{scriptsize}
  \begin{minted}{pycon}
>>> re.match('<.*>', '<h1>Title</h1>').group()
'<h1>Title</h1>'
>>> re.match('<.*?>', '<h1>Title</h1>').group()
'<h1>'
  \end{minted}
  \end{scriptsize}
 \end{itemize}
\end{frame}
\end{document}
