\makeatletter
\@ifundefined{complet}
{\documentclass[10pt]{report}
\title{Python}
\newcommand{\categorie}{Python}
\input{latex_entete_perso}

\begin{document} %Cours

\setcounter{chapter}{12}
% xelatex -shell-escape cours_python
}
{}
\makeatother



\chapter{Conditions}




\section{Booléens}

\begin{multicols}{2}


\subsection{Booléen \small{voir Type simple 4.3}}


\subsection{Vocabulaire \small{voir Type simple 6.2.3}}

\small{Expression - Instruction - Affectation}


\subsection{Créer un booléen avec bool() \small{voir Type simple 4.4.5} }

Un contenu VIDE/NUL est évalué à False si on veut un booléen. Sinon, le résultat est False.

\end{multicols}



\section{Instruction conditionnelle SI, SINON SI, SINON}

\begin{multicols}{2}


\subsection{Instruction conditionnelle \small{voir Intro 1.4.4}}


\subsection{Structure générale}

Quelque soit le langage, on retrouve toujours une structure qui ressemble à ceci :

Un contenu VIDE/NUL est évalué à False si on veut un booléen. Sinon, le résultat est False.

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{bash}
Instructions Avant 1
Instructions Avant 2

# BLOC A (un seul, obligatoire)
SI une expr. booléenne A est vraie        
    Instruction A1
    Instruction A2

# BLOC B (0 ou + : optionnel) 
SINON SI une expr. bool. B est vraie  
    Instruction B1
    Instruction B2
 
# BLOC C (0 ou 1 : optionnel unique)
SINON (dans tous les autres cas)               
    Instruction C1
    Instruction C2

Instructions Après 1
Instructions Après 2
\end{minted}


\paragraph{Nombre de blocs}

\begin{itemize}

\item Un unique bloc SI et il doit toujours être en première position
\item 0, 1, 2 ou autant de blocs SINON SI que vous voulez
\item 0 ou 1 bloc SINON et il doit toujours être en dernière position : c'est le bloc par défaut. Si aucun autre n'a été activé, on prend celui-ci.

\end{itemize}



\subsection{Un seul bloc exécuté}

\paragraph{A SAVOIR IMPERATIVEMENT}

L'interpréteur Python n'exécute que \gras{l'un des blocs} A, B ou C d'une structure if-elif-else.

Il exécute les instructions du bloc de la première expression évaluée à True puis quitte la structure \gras{même si les autres expressions sont vraies également}.


\paragraph{Un exemple de déroulement}:


\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
Instructions Avant 1
Instructions Avant 2
 
# BLOC A (un seul, obligatoire)
if note > 11:
    Instruction A1                                  
    Instruction A2                                  
    Instruction A3                                  
 
# BLOC B (0 ou + : optionnel)         
elif note < 9:
    Instruction B1                                  
    Instruction B2                                  
    Instruction B3                                  
 
# BLOC C (0 ou 1 : optionnel unique)  
else:              
    Instruction C1                                  
    Instruction C2                                  
 
Instructions Après 1
Instructions Après 2
\end{minted}


\paragraph{Exemple avec note valant 15}.

C'est le bloc A qui va s'activer car note > 11 est évaluée à True.

Il exécute L1-L2-L5-L6-L7-L8-L21-L22.

\paragraph{Exemple avec note valant 5}.

C'est le bloc B qui va s'activer car le bloc A ne sera pas activé et note < 9 est évaluée à True.

Il exécute L1-L2-L5-L11-L12-L13-L14-L21-L22.

\paragraph{Exemple avec note valant 9}.

C'est le bloc C qui va s'activer car le bloc A ne sera pas activé, le bloc B non plus (9 n'est pas strictement inférieur à 9) et le else ne possède jamais de condition : si on y arrive, on le déclenche toujours.

Il exécute L1-L2-L5--L11-L17-L8-L19-L21-L22.




\subsection{Instruction conditionnelle et fonction}

\subsubsection{Version propre avec une seule "porte de sortie"}

\begin{itemize}
\item AVANTAGE : plus facile de surveiller la correction de la fonction (le fait que la fonction réponde toujours correctement)
\item DESAVANTAGE : il faut stocker la réponse dans une variable et lire ensuite séquentiellement la fonction jusqu'à trouver l'unique sortie.
\end{itemize}


\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def appreciation(note:int) -> str:
    if note > 13:
        app = "Bien"
    elif note < 9:
        app = "Insuffisant"
    else:
        app = "Moyen"
    return app
\end{minted}





\subsubsection{Version avec plusieurs "portes de sortie"}

\begin{itemize}
\item AVANTAGE : on n'a pas besoin en tant que lecteur humain de continuer à lire le reste du code lorsqu'on rencontre une sortie.
\item DESAVANTAGE : moins facile à surveiller (plusieurs portes de sortie à contrôler).
\end{itemize}




\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def appreciation(note:int) -> str:
    if note > 13:
         return "Bien"
    elif note < 9:
        return "Insuffisant"
    else
        return "Moyen"
\end{minted}


\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def appreciation(note:int) -> str:
    if note > 13:
         return "Bien"
    elif note < 9:
        return "Insuffisant"
    return "Moyen"
\end{minted}


\subsubsection{Exemple de vérification avant envoi}

Une seule sortie : une seule vérification.

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def beaucoup_trop_gentil(note:int) -> int:
    if note < 10:
        note = note + 5
    else:
        note = note + 3
    # Vérification avant envoi
    if note > 20:
        note = 20
    return note
\end{minted}

Deux sorties : deux vérifications...

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def beaucoup_trop_gentil(note:int) -> int:
    if note < 10:
        note = note + 5
        # Vérification avant envoi
        if note > 20:
            note = 20
        return note
    else:
        note = note + 3
        # Vérification avant envoi
        if note > 20:
            note = 20
        return note
\end{minted}

\end{multicols}




\section{Prédicat : fonction renvoyant un booléen}

\begin{multicols}{2}


\subsection{Opérateurs == et =}

Attention à ne pas confondre

\begin{itemize}
\item l'opérateur d'égalité de contenu \fo{==}
\item l'opérateur d'affectation \fo{=}
\end{itemize}

Avec \fo{a == b}, l'interpréteur comprend qu'il doit tester l'égalité des variables \fo{a} et \fo{b}. Il va donc évaluer cette expression et obtenir vrai si les deux contenus sont les mêmes.

Avec \fo{a = b}, l'interpréteur comprend qu'il faut stocker \fo{b} dans la variable \fo{a}. On génère donc un alias.





\subsection{FONCTION : Prédicat}

\subsubsection{Forme typique de prédicat}

On peut nommer de cette façon une fonction qui renvoie toujours un booléen : elle répondra soit \fo{True} soit \fo{False}.

On parle de prédicat puisque la fonction prédit une propriété à partir des paramètres reçus.

Ce cas de figure est très courant en informatique : créer un prédicat ne requiert donc forcément pas d'utiliser un if : il suffit de fournir l'expression qu'on veut évaluer derrière votre return.

Exemple avec une fonction qui évalue si une note de 10 permet de valider un semestre :

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def est_valide(note:int) -> bool:
    """Renvoie True si la note >= 10"""
    return note >= 10
\end{minted}


\subsubsection{La version à éviter tant que c'est possible}

La version ci-dessous est valide également mais est à éviter si possible : elle revient à dire "si c'est vrai, dis que c'est vrai, sinon, dis que c'est faux". Un peu lourd. Et l'oubli du else est très courant : on finit par avoir une fonction qui dit bien quand c'est vrai mais qui ne répond rien quand c'est faux.

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
def est_valide(note:int) -> bool:
    """Renvoie True si la note >= 10"""
    if note >= 10:
        return True
    else:
        return False
\end{minted}


\end{multicols}



\section{If sans condition booléenne ?}

\begin{multicols}{2}


\subsection{Condition non booléenne}


\subsubsection{Cas d'une expression booléenne}

Lorsque l'interpréteur Python lit un \fo{if} ou un \fo{elif}, il s'attend à trouver une expression booléenne derrière.

Exemple : \fo{if a >= 0:}

Ici, l'expression est bien une expression booléenne.

\subsubsection{Cas d'une expression non booléenne}

Il peut arriver par contre que l'expression fournie ne soit pas une expression booléenne.

Exemple : \fo{if a:}

Python ne va alors pas s'embêter : il va chercher à l'interpréter comme un booléen, comme si vous aviez tapé ceci :

Exemple : \fo{if bool(a):}

Ainsi :

    Si \fo{a} est nul, vide ("" ou [] ou () ou {}) ou None, \fo{a} sera équivalent à un \fo{False}.
    
    Dans tous les autres cas, \fo{a} sera équivalent à \fo{True}.



\subsection{Cas du tableau vide}

On peut agir en fonction de l'état VIDE ou NON VIDE d'un type construit en utilisant une simple instruction conditionnelle.

Voici comment agir de façon différente\gras{si le tableau est NON VIDE} et sinon s'il est VIDE :


\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
if tab:  # si tab est NON VIDE
    actions_si_le_tableau_n_est_pas_vide
 
else:  # sinon, c'est que tab est VIDE
    actions_si_le_tableau_est_vide
\end{minted}

Le mot-clé \fo{not} permet d'inverser la valeur booléenne : vrai devient faux, et faux devient vrai. On peut alors demander ainsi d'agir \fo{si le tableau est VIDE}, et sinon s'il est NON VIDE:

\begin{minted}[linenos=true, bgcolor=lightgray, tabsize=4, gobble=0, fontfamily=courier, fontsize=\small, xleftmargin=20pt, xrightmargin=5pt]{python}
if not tab:  # tab est vide 
    actions_si_le_tableau_est_vide
 
else:  # sinon, c'est que tab est vide
    actions_si_le_tableau_est_vide
\end{minted}

Dans le dernier cas, notez que si \fo{tab} est évalué à \fo{False}, alors \fo{not tab} sera évaluée à {True}.



\end{multicols}



\input{licence}

\makeatletter
\@ifundefined{complet}
{\end{document}}

{}
\makeatother

