====== Aspect séquentiel des opérateurs logiques ====== Nous allons voir que Python -- comme beaucoup de langages -- ajoute un ingrédient dans les opérateurs ''and'' et ''or''. Ce nouvel ingrédient ne change rien à ce que vous savez déjà, donc si ce qui suit vous parait trop compliqué -- c'est assez compliqué... -- ce n'est pas grave : C'est vraiment un tout petit détail, vous pouvez faire l'impasse dessus. ===== Nouvelle définition ===== ==== or ==== **Ancienne :** ''a or b or c or ...'' vrai si et seulement si au moins une des opérandes est vraie, faux sinon. **Nouvelle :** ''a or b or c or ...'' * cherche la première opérande vraie, * renvoie cette opérande et ne va pas plus loin si trouvée, * sinon renvoie la dernière opérande. Cela parait plus compliqué. Cela ne change rien tant que l'on a des booléens normaux. Mais justement, on a le droit d'utiliser ''or'' avec autre chose que des booléens ! >>> "chien" or "chat" "chien" >>> 13 or 28 13 Analysons le premier cas : * ''%%"chien" or "chat"%%'', Python identifie le ''or''. Les textes ''%%"chien"%%'' et ''%%"chat"%%'' seront interprétés en tant que booléens, * Python lit le premier. ''%%"chien"%%'', n'est pas un texte vide, est compris comme ''True''. * Puisque Python a trouvé dans le ''or'' un premier élément ''True'', il le renvoie et ne va pas plus loin. Mais **Attention :** Python ne renvoie pas ''True'' mais l'opérande lui-même, c'est à dire ''%%"chien"%%''. ==== and ==== **Ancienne :** ''a and b and c and ...'' faux si et seulement si au moins une des opérandes est fausse, vrai sinon. **Nouvelle :** ''a and b and c and ...'' * cherche la première opérande fausse, * renvoie cette opérande et ne va pas plus loin si trouvée, * sinon renvoie la dernière opérande. >>> "chien" and "chat" "chat" >>> 13 and 28 28 Analysons le premier cas : * ''%%"chien" and "chat"%%'', Python identifie le ''and''. Les textes ''%%"chien"%%'' et ''%%"chat"%%'' seront interprétés en tant que booléens, * Python lit le premier. ''%%"chien"%%'', n'est pas un texte vide, est compris comme ''True''. * Python n'ayant pas trouvé False, il passe au suivant : ''%%"chat"%%''. * ''%%"chat"%%'' n'est pas vide non plus, donc compris comme ''True''. Python passe au suivant. * Mais il n'y a pas de suivant. Python renvoie donc le dernier rencontré : ''%%chat%%''. ===== Quel intérêt ? ===== Cette nouvelle définition est beaucoup plus compliquée. Il faut qu'elle serve à quelque chose. Il y a deux grandes applications. Peut-être vous paraîtront-elles un peu maigre pour justifier de compliquer ainsi les choses. Mais ces astuces sont pourtant très très utilisées. Bien sûr, pour des débutants en programmation, on peut laisser tout cela de côté et y revenir plus tard. ==== Application 1 : évacuer les cas à problème ==== Supposons que ''L'' soit un sorte de liste d'éléments, par exemple ''L = [4, 17, 32, 25]'' et que l'on veuille comparer le premier et le dernier élément de cette liste. Dans le cas où le dernier est plus grand que le premier, on voudrait afficher "A augmenté" et sinon "N'a pas augmenté". Voilà une première approche : if premier_element(L) < dernier_element(L): print("A augmenté") else: print("N'a pas augmenté") Mais ''L'' pourrait être vide, si bien que ''%%premier_element(L)%%'' déclencherait une erreur puisque si ''L'' est vide, elle n'a pas de premier élément... On pourrait changer ainsi : if not est_vide(L): if premier_element(L) < dernier_element(L): print("A augmenté") else: print("N'a pas augmenté") else: print("N'a pas augmenté") C'est bien mais un peu lourd : * imbrication de ''if'' -- que l'on pourrait éviter en utilisant ''elif'', * deux fois le même ''print''. On préfère ceci : if not est_vide(L) and premier_element(L) < dernier_element(L): print("A augmenté") else: print("N'a pas augmenté") Ici, en ligne 1, si ''%%est_vide(L)%%'' est ''True'', ''%%not est_vide(L)%%'' est ''False'', ce qui interrompt l'évaluation du ''and'' qui renvoie ''False''. **Comprenez bien :** dans le cas ou ''L'' est vide, l'évaluation de la condition en ligne 1 ne va pas au bout. ''%%premier_element(L)%%'' n'est pas exécuté et il n'y a donc pas d'erreur. ==== Application 2 : Valeurs par défaut ==== Supposons que je demande à l'utilisateur de donner un nom au clavier. L'utilisateur est libre de donner un nom vide. Dans ce cas je souhaite imposer un nom par défaut. On pourrait faire ceci : nom = input("Donnez un nom :") if nom == "": nom = "nom par défaut" # suite du programme Mais on aime faire ceci : nom = input("Donnez un nom :") or "nom par défaut" # suite du programme **Analysons ce qui se passe :** * Python évalue la parti droite de ''=''. * Python reconnaît un ''or'', il parcours les opérandes à la recherche d'une opérande vraie. * Python lit ''%%input("Donnez un nom :")%%'' et l'exécute donc. * Premier cas, l'utilisateur répond quelque chose, par exemple ''%%"Klein"%%'', * ''%%"Klein"%%'' est un texte non vide, compris comme ''True'' dans ce cas. * Python n'a pas besoin d'aller plus loin dans l'évaluation du ''or'', il renvoie la valeur trouvée : ''%%"Klein"%%'' * ''nom'' prend donc la valeur ''%%"Klein"%%'' * Deuxième cas, l'utilisateur répond une chaîne vide ''%%""%%'', * La chaîne vide est comprise comme ''False'' dans ce cas, * Python continue donc à parcourir les opérandes de ''or'', * Python lit ''%%"nom par défaut"%%'' qui n'est pas vide, donc compris comme ''True'', * Le ''or'' renvoie donc cette dernière opérande, ''%%"nom par défaut"%%'',\\ De toutes façons, c'est la dernière opérande. //or// ne pouvait pas aller plus loin. * ''nom'' prend donc la valeur ''%%"nom par défaut"%%''