\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[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 beginner]{Python\\niveau débutant}


% 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}

\newcommand{\python}[1]{\mintinline{python}{#1}}

\begin{document}

\begin{frame}
 \maketitle
 \begin{center}
  \includegraphics[width=0.2\linewidth]{images/logo-python.pdf}
 \end{center}
\begin{small}
 (librement inspiré des \href{https://wiki.crans.org/CransTechnique/CransApprentis/SeminairesTechniques/2012-2013?action=AttachFile&do=view&target=shell_ssh.pdf}{slides} de Pauline \textsc{Pommeret})
\end{small}
\end{frame}

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


\section{Introduction}
\subsection{Présentation}
\begin{frame}
 \frametitle{C'est quoi ?}
 Python est un langage de programmation :
 \begin{itemize}
  \item interprété (exécuté par un interpréteur, par opposition à compilé)
  \item orienté objet (tout est objet, que l'on définit et manipule)
  \item impératif (suite d'instructions)
  \item à typage dynamique (détections des erreurs de type à l'exécution, c'est-à-dire le plus tard possible) fort (peu de conversions implicites)
  \item équipé d'un garbage collector (qui gère la mémoire à votre place) et d'un système de gestion d'exceptions (affiche un message au lieu de crasher bêtement)
  \item multi-plateforme (implémentations sous Windows, Linux, Mac OS)
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Pourquoi l'utiliser ?}
 \begin{itemize}
  \item Relativement simple, souple et facile à apprendre
  \item Bibliothèque standard très fournie
  \item Plus succint : \textit{Life is short, you need Python!}\footnote{Bruce Eckel, membre du comité de normalisation du C++ et auteur de Thinking in Java}
  \item Dans \textit{/usr/scripts/}, on trouve 486 scripts en Python
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Comment l'utiliser ?}
 \begin{itemize}
  \item python en mode « interactif »
  \begin{itemize}
   \item \texttt{python}
   \item \texttt{ipython}
   \item \texttt{bpython}
  \end{itemize}
  \item exécuter un script python
  \begin{itemize}
   \item \texttt{python script.py}
   \item exécuter directement \texttt{./script.py} si :
   \begin{itemize}
    \item il est exécutable (\texttt{chmod +x script.py})
    \item il commence par un shebang \texttt{\#!/usr/bin/env python}\footnote{Au Cr@ns, préférer \texttt{/usr/scripts/python.sh}, qui fait en sorte qu'on puisse importer facilement les scripts de \texttt{/usr/scripts/}.}
    \item il est correctement encodé\footnote{L'encodage du fichier doit correspondre à l'encodage déclaré}
   \end{itemize}
  \end{itemize}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Avec quoi je code ?}
 Avec votre éditeur de texte favori.
 \begin{itemize}
  \item \texttt{nano}, \texttt{vim}, \texttt{emacs}
  \item SciTE, Kate, Eclipse (avec le plugin PyDev), Code::Blocks, Python IDE (pour les windowsiens endurcis), Xcode (sous Mac OS)
 \end{itemize}
 
 \textbf{Attention}, Si mon fichier \texttt{essai.py} contient

\python{print "essai : é"}

 et que je fais naïvement \texttt{python essai.py}, j'obtiens

\texttt{SyntaxError: Non-ASCII character '\textbackslash xc3' in file a.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details}

Il faut ajouter à la deuxième ligne du fichier :
\begin{minted}[comment=NA]{python}
# -*- encoding: utf-8 -*-
\end{minted}
\end{frame}

\section{Les types}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}
\subsection{Introduction}
\begin{frame}
 \frametitle{Les types}
 \begin{itemize}
  \item En python, tout est objet. Un objet peut être assigné à une variable, passé comme paramètre à une fonction.
  \item Chaque objet a un type
  \item Pour le connaître : \python{type(objet)}
  \item Python possède de base plein de types dits \texttt{built-in}
 \end{itemize}
\end{frame}

\subsection{Les types simples}
\begin{frame}
 \frametitle{Types simples}
 \begin{itemize}
  \item \python{int} : entier signé compris entre\footnote{si vous êtes en architecture 32bits, 63 est à remplacer par 31} $-2^{63} + 1$ et $2^{63} - 1$ (\python{0, 1, -5})
  \item \python{long} : entier arbitrairement long (\python{0L, 9223372036854775808L})
  \item \python{float} : nombre à virgule (\python{0.3, 2e+45})
  \item \python{str} : chaîne de caractères, aussi appelée chaîne d'octets (\python{"a", "plo\nuf"})
  \item \python{unicode} : chaîne unicode, suite de points de code unicode (\python{u"a"}) (cf \href{fra:encodage}{encodages})
  \item \python{bool} : booléen, il n'en existe que deux : \python{True} et \python{False}
  \item \python{NoneType} : un seul objet : \python{None}. C'est le "rien" de Python. (Il est typiquement renvoyé par une fonction qui ne renvoie pas de résultat.)
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Manipulation des chaînes}
 \begin{itemize}
  \item \python{s = "chAinE exEmple"}
  \item \python{s.upper()} : \python{"CHAINE EXEMPLE"}
  \item \python{s.lower()} : \python{"chaine exemple"}
  \item \python{s.capitalize()} : \python{"Chaine exemple"}
  \item \python{s.title()} : \python{"Chaine Exemple"}
  \item \python{s = "j'ai une apostrophe"}
  \item \python{s = 'je "cite"'}
  \item \python{s = "je \"m'élange\""}
  \item \begin{minted}{python}
s = """Je n'ai pas à me soucier
des "guillemets"
ni des retours à la ligne"""
\end{minted}
  \item \python{s.replace("avant", "apres")} : remplace toutes les occurrences
  \item \python{len(s)} : longueur de la chaîne
 \end{itemize}
\end{frame}

\subsection{Les types composés}

\begin{frame}
 \frametitle{Types composés}
 \begin{itemize}
  \item \python{list} : liste d'objets (pas forcément de même type)
  \begin{itemize}
   \item déclarer une liste : \python{l = [3, "a", []]}
   \item accéder à un élément : \python{l[0], l[2], l[-1]}
   \item sélectionner une sous-liste : \python{l[2:5]}
   \item ajouter un élément : \python{l.append(42)} ou \python{l.insert(2, "b")}
   \item retirer un élément : \python{del l[1]} ou \python{l.remove("a")} ou \python{valeur = l.pop(2)}
   \item affecter un élément : \python{l[0] = 4}
   \item concaténer des listes : \python{l1.extend(l2)}
  \end{itemize}
  \item \python{tuple} : n-uplet.
  \begin{itemize}
   \item déclarer un tuple : \python{t = (4, "abc")}
   \item tuple vide : \python{()}, tuple à un élément : \python{(1,)}
   \item accéder à un élément : \python{t[0], t[1]}
  \end{itemize}
  \item \python{len(l)} : obtenir la longueur
  \item NB: pas de "tableau" en python, la liste a le comportement qu'on attend d'un tableau.
  \item Un \python{tuple} n'est pas mutable : on ne peut pas modifier/ajouter des éléments.
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Table de hashage}
 \python{dict} : dictionnaire, associe une valeur à chaque clé
 \begin{itemize}
  \item déclarer un dictionnaire : \python{d = {"a" : 26, 5 : []}}
  \item accéder à une valeur : \python{d[5]}
  \item ajouter une clé/remplacer une valeur : \python{d[5] = "valeur"}
  \item retirer une valeur : \python{del d["a"]} ou \python{valeur = d.pop(5)}
  \item accéder à une valeur sans échouer : \python{d.get(6)} (renverra \python{None} si la clé \python{6} n'existe pas) ou \python{d.get(6, "rien")} (renverra \python{"rien"} si la clé \python{6} n'existe pas).
 \end{itemize}
\end{frame}

\section{Les instructions}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}
\subsection{Introduction}
\begin{frame}[fragile]
 \frametitle{Les instructions}
 \begin{itemize}
  \item Elles servent à construire le code.
  \item Ce sont des mots-clés réservés
  \item Il y en a exactement 26 :
  \begin{minted}{python}
as assert break class continue def del elif
else except exec finally for from global if
import lambda pass print raise return try 
while with yield
\end{minted}

   (Si on ajoute \python{and or in is not} (opérateurs booléens), on a les 31 keywords réservés\footnote{Vous ne pouvez pas les utiliser comme nom de variable} de Python).
   \item On va voir l'utilité d'un certain nombre d'entre eux.
  \end{itemize}
\end{frame}

\subsection{Instructions simples}
\begin{frame}
 \frametitle{Affichage}
 \python{print}
 \begin{itemize}
  \item \python{print mon_objet}
  \item Affiche la représentation sous forme de texte de l'objet
  \item Appelle la méthode spéciale \python{mon_objet.__str__()}\footnote{cf la programmation orientée objet, séminaire python advanced}
  \item Attention, en python3, \python{print} n'est plus une instruction et doit être utilisée comme une fonction : \python{print("a")}
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Contrôle de flux}
 En python, l'indentation des blocs est obligatoire et a un sens.
 \begin{itemize}
  \item \begin{minted}{python}
if condition1:
    instruction si condition1 est vraie
elif condition2:
    instruction si condition1 est fausse
    et condition2 est vraie
else:
    instruction si les deux sont fausses
\end{minted}
  \item Les blocs \python{elif} et \python{else} sont facultatifs
  \item Les \python{conditions} peuvent être :
  \begin{itemize}
   \item un booléen : \python{True}, \python{False}
   \item une expression dont le calcul donne un booléen : \python{a < 3}
   \item un autre objet : \python{"plouf"}
   
   Il est alors \textbf{converti} en \python{bool}.
   \item \python{None, False, 0, 0L, 0.0, 0j, "", [], (), {}} et \python{set()} sont convertis en \python{False}, le reste\footnote{Sauf un objet défini par l'utilisateur pour se comporter autrement.} en \python{True} (par exemple : \python{"False"}).
  \end{itemize}
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Opérateurs}
\begin{center}
 \begin{tabular}{|c|l|}
 \hline
 \multicolumn{2}{|c|}{Opérateurs booléens}\\
 \hline
 \python{<} / \python{>} & strictement inférieur/supérieur à\\
 \hline
 \python{<=} / \python{>=} & inférieur/supérieur ou égal à\\
 \hline
 \python{==} & égal à\\
 \hline
 \python{!=} & différent de\\
 \hline
 \python{e in l} & appartient à (\python{l} doit être itérable)\\
 \hline
 \python{o is objet} & est le même objet dans la mémoire\\
 \hline
 \python{not / and / or} & non/et/ou booléens\footnote{Attention si on ne les utilise pas avec des booléens}\\
 \hline
 \end{tabular}
 
 \begin{tabular}{|c|l|}
 \hline
 \multicolumn{2}{|c|}{Opérateurs de calcul\footnote{Ces opérateurs appellent la fonction spéciale (par exemple \python{.__add__()}) du premier sur le deuxième. Cf python advanced.}}\\
 \hline
 \python{+} & addition, concaténation\\
 \hline
 \python{- / *} & soustraction, division (entière), multiplication\\
 \hline
 \python{**} & exponentiation\\
 \hline
 \texttt{\%} & modulo\\
 \hline
 \end{tabular}
\end{center}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Les boucles}
 \begin{itemize}
  \item \begin{minted}{python}
for i in [0, 1, 2, 3, 4, 5, 6]:
    if i == 0:
        continue # passe à l'itération suivante
    elif i == 4:
        break    # interrompt la boucle
    print i,

1 2 3
\end{minted}
  \item \begin{minted}{python}
while condition:
    corps de la boucle
\end{minted}
  \item si \python{condition} est fausse, aucune instruction n'est exécutée.
  \item \python{continue} et \python{break} fonctionnent aussi
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Les boucles : astuces}
 \begin{itemize}
  \item \python{enumerate} est une fonction built-in qui prend une liste et retourne la liste des couples (indice, élément).
  \item \begin{minted}{python}
for (i, e) in enumerate(l):
    print "L'élément {} est {}".format(i, e)  
\end{minted}
  \item Les dictionnaire ont une méthode \python{.iteritems()} qui permet de parcourir les couples (clé, valeur).
  \item \begin{minted}{python}
for (k, v) in d.iteritems():
    print "v={}, k={}".format(v, k)
\end{minted}
 \end{itemize}
\end{frame}

\subsection{Les erreurs}
\begin{frame}
 \frametitle{Gestion des erreurs}
 \begin{itemize}
  \item Une "erreur" en Python s'appelle une exception.
  \item Les exceptions sont des objets dont le type dépend de la raison de l'erreur.
  \item Elles héritent toutes de \python{BaseException}
  \item Il existe \python{SystemExit} (l'intépréteur va quitter), \python{KeyboardInterrupt} (levée en cas de Ctrl+C ou de réception d'un SIGINT). Et enfin \python{Exception}, dont héritent toutes les "vraies" exceptions.
  \item On rattrape toujours un \textbf{type} d'erreur. Donc ça inclus les exceptions de ce type, mais aussi de tous ceux qui en héritent.
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{\python{try, except, finally} et \python{raise}}
\begin{minted}{python}
try:
    print 1/a
    print "la division a réussi"
except ZeroDivisionError as e:
    print "a vaut 0, on ne peut pas diviser"
except NameError as e:
    # autre erreur, autre action
    print "la variable a n'existe pas"
    raise ValueError("erreur levée manuellement")
except (TypeError, ValueError) as e:
    # pour faire la même chose pour ces deux erreurs
    print "Erreur de type %s, on s'arrête" % (type(e))
    raise # Relève la même erreur (e)
finally:
    # bloc toujours exécuté, même si il y eu un raise
    print "dans tous les cas j'affiche ça"
\end{minted}
\end{frame}

\section{Les fonctions}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}
\subsection{Fabriquer ses fonctions}
\begin{frame}[fragile]
 \frametitle{Fabriquer ses fonctions}
 \begin{itemize}
  \item \begin{minted}{python}
def mafonction(param1, param2):
    """ Explication sur ma fonction. """
    if un_cas:
        return param1 ** param2 + 42
    elif un_deuxieme_cas:
        return
        # ce code ne sera jamais lu
        print "jamais affiché"
    else:
        print "quelque chose"
\end{minted}
  \item Sans \python{return} ou avec \python{return} mais sans objet, la fonction renverra \python{None}
 \end{itemize}
\end{frame}

\subsection{Fonctions built-in}
\begin{frame}
 \frametitle{Des fonctions built-in}
 \begin{itemize}
  \item On peut les écraser, mais on a intérêt à savoir ce qu'on fait.
  \item \python{int, float, str, unicode, list, tuple} : convertissent en le type correspondant (NB : \python{int("2F", 16)}).
  \item \python{enumerate, len} : cf avant
  \item \python{open} : pour ouvrir un fichier\footnote{cf séminaire advanced}
  \item \python{range(5)} : renvoie la liste \python{[0, 1, 2, 3, 4]}
  \item \python{zip([1, 2, 3, 4], ["a", "b", "c"])} renvoie la liste des paires \python{[(1, 'a'), (2, 'b'), (3, 'c')]} (s'arrête dès qu'une liste est épuisée)
  \item \python{sum(l)} : renvoie la somme des éléments. On peut donner un élément de départ : \python{sum([[5], [6]], [])} (calcul \textit{in place} donc ne marche pas avec des strings)
 \end{itemize}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item \python{all(l)} : renvoie \python{True} si tous les éléments de \python{l} sont vrais.
  \item \python{any(l)} : renvoie \python{True} si au moins un des éléments de \python{l} est vrai.
  \item \python{bin(x), hex(x), oct(x)} : renvoie la représentation en binaire/hexadécimal/octal du nombre (un string)
  \item \python{chr(i), unichr(i) / ord(c)} : renvoie le i-ème caractère de la table ASCII, ou unicode / renvoie le numéro dans la table du caractère (\python{ord} marche au-delà de 255, pas de uniord).
  \item \python{cmp(x, y)} : \python{-1} si \python{x < y}, \python{0} si \python{x == y}, \python{1} si \python{x > y}
  \item \python{divmod(a, b)} : renvoie \python{(quotient, reste)}
  \item \python{eval("a = 5 + 3")} : ça marche. Faites vraiment attention. N'utilisez pas ça.
  \item \python{filter(fonction_test, l)} : renvoie la liste des objets pour lesquels le test est vrai. Renvoie un \python{str} ou un \python{tuple} si c'est le type de \python{l}.
 \end{itemize}
\end{frame}

\begin{frame}
 \begin{itemize}
  \item \python{isinstance(o, typ)} : la bonne méthode pour tester le type d'un objet.
  
  \python{type(i) == int} c'est mal. \python{type(i) == type(0)}, c'est pire. \python{isinstance(i, int)} c'est bien.
  
  Cas très utile : \python{isinstance(s, basestring)} (vrai si \python{s} est de type  \python{unicode} \textbf{ou} \python{str})
  \item \python{issubclass(classe1, classe2)} : teste si un type est un sous-type d'un autre.
  
  Pour ces deux fonctions, le deuxième paramètre peut être un tuple de classe et le test fera un \textbf{ou}.
  \item \python{map(f, l1, l2)} : renvoie \python{[f(l1[0], l2[0]), f(l1[1], l2[1]), ...]}. Complète les listes trop courtes avec des \python{None}. (on peut donner un nombre quelconque de listes)
  \item \python{max(l), min(l)} : renvoie le maximum/minimum d'un itérable. Lève une erreur si il est vide.
  
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Intéraction avec l'utilisateur}
 \begin{itemize}
  \item \python{s = raw_input("Entrez un texte :")} : récupère un string entré par l'utilisateur (le paramètre est optionnel).
  \item \python{a = input("Valeur de a :")} : équivalent à \python{eval(raw_input())}. Attention :
  \begin{itemize}
   \item L'utilisateur doit entrer une expression Python valide, sous peine de levée d'exception
   \item L'utilisateur a alors accès à toute variable de votre programme\ldots
  \end{itemize}
 \end{itemize}
\end{frame}

\subsection{Les modules}
\begin{frame}
 \frametitle{Les modules}
 \begin{itemize}
  \item \python{import module} puis \python{module.fonction()}
  \item \python{from module import fonction} puis \python{fonction()}. Utile quand on n'en a besoin que d'une ou deux.
  \item \python{from module import *} : ne faites \textbf{jamais} ça.
  \item \python{import module_au_nom_beaucoup_trop_long as  mod} puis \python{mod.fonction()} : raccourci pratique.
  \item \python{from module import fonction_au_nom_long as foo} puis \python{foo()}.
  \item Si on a importé sans utiliser \python{from}, on peut faire \python{reload(module)} pour recharger le module si il a été modifié (si on a utilisé \python{as mod} il faut appeler \python{reload(mod)}).
 \end{itemize}
\end{frame}
\section{Protips}
\begin{frame}
 \tableofcontents[currentsection]
\end{frame}
\subsection{Encodage}
\begin{frame}
 \label{fra:encodage}
 \frametitle{Point sur l'encodage}
 \begin{itemize}
  \item Python manipule des chaînes de caractères (type \python{str}) et des chaînes unicode (type \python{unicode})
  \item \python{str} $\underset{\text{encodage}}{\overset{\text{décodage}}{\rightleftarrows}}$ \python{unicode}
  \item Pour passer de l'un à l'autre, il faut un \textbf{encodage}
  \item \python{u"àé"} est une chaîne unicode, elle est représentée dans la mémoire comme une liste de points de codes unicode (le 224ème et le 234ème)
  \item Si on l'\textbf{encode} avec l'encodage \texttt{UTF-8}, on obtient une chaîne de caractères \python{"àé"} représentée dans la mémoire par une suite d'octets (195, 169, 195, 160). Avec un autre encodage, ce sera différent.
  \item Si on \textbf{décode} cette chaîne avec l'encodage \texttt{ISO8859-1}, on obtient \python{u"Ã Ã©"}. Si vous rencontrez ça, il y a de grandes chances que quelqu'un ait mal géré l'encodage.
 \end{itemize}
\end{frame}

\begin{frame}[fragile]
 \frametitle{Point sur l'encodage}
 \begin{itemize}
  \item Python fait des \textbf{conversions implicites} :  \python{u"a" + "b"} marchera (et donnera un \python{unicode})
  \item Tant que les chaînes ne sortent pas de la table ASCII, tout va bien, car c'est l'encodage utilisé pour les conversions implicites. Mais \python{u"a" + "é"} lèvera une \python{UnicodeDecodeError}.
  \item Utilisez toujours des \python{unicode} pour travailler
  \item \textbf{Décodez} au plus vite vers l'unicode les chaînes que vous récupérez (depuis l'utilisateur, un fichier, le réseau\ldots) et \textbf{encodez} le plus tard possible vers des chaînes d'octets au moment de faire un output (mais n'oubliez pas de le faire).
 \end{itemize}
 Un fichier enregistré sur le disque est une suite d'octets placés là par votre éditeur. Python a besoin de savoir dans quel encodage il est écrit pour comprendre ce que vous y avez mis. C'est à ça que lui sert cette ligne
\begin{minted}[comment=NA]{python}
# -*- coding: utf-8 -*-
\end{minted}
\end{frame}

\subsection{Bonnes pratiques}
\begin{frame}[fragile]
 \frametitle{Philosophie python, bonne pratiques}
 \begin{itemize}
  \item DRY : \textit{Don't Repeat Yourself}. Si vous recopiez des bouts des codes, quelque chose ne va pas.
  \item Respectez la \href{http://www.python.org/dev/peps/pep-0008/}{PEP8}
  \item Commentez votre code, surtout si vous faites quelque chose d'inattendu.
  \item Mettez des docstrings :
  \begin{minted}{python}
def ma_fonction(param):
    """Cette fonction fait ceci avec ``param``"""
    ...
\end{minted}
  \item Découpez un code trop long en modules
  \item N'utilisez pas de variables globales
 \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{\texttt{ipython}}
 \begin{itemize}
  \item tab-complétion
  \item \mintinline{pycon}{objet?} $\rightarrow$ donne de l'aide sur l'objet
  \item bonne gestion de l'historique
  \item tab-complétion
  \item \texttt{run monscript.py} pour le lancer dans \texttt{ipython}
  \item \texttt{!cat plouf} pour exécuter une commande shell depuis \texttt{ipython}
 \end{itemize}
\end{frame}

\subsection{Conclusion}
\begin{frame}
 \frametitle{Conclusion}
 \begin{itemize}
  \item Gardez la doc à portée de main : \href{http://docs.python.org}{http://docs.python.org} (attention à la version)
  \item Dans le séminaire advanced, on parlera de
  \begin{itemize}
   \item classe d'objets, comment les définir
   \item surcharge
   \item héritage
   \item itérateurs et compréhension
   \item plus de modules standards
  \end{itemize}
 \end{itemize}
\end{frame}
\end{document}
