Bien plus compréhensible qu'avec `>>>`master
| @@ -1,2 +1,5 @@ | |||||
| explication des exercices | explication des exercices | ||||
| insérer exercices pour chaque épisode de la saison 2 | insérer exercices pour chaque épisode de la saison 2 | ||||
| Explications sur `globals()` et `locals()` | |||||
| @@ -74,3 +74,18 @@ et on peut utiliser des parenthèses pour grouper les opérations:: | |||||
| print((1 + 2) * 3) | print((1 + 2) * 3) | ||||
| # affiche: 9 | # affiche: 9 | ||||
| Combiner opération et assignation | |||||
| ---------------------------------- | |||||
| La notation ``+=`` permet de combiner addition et assignation:: | |||||
| x = 3 | |||||
| x = x + 1 | |||||
| print(x) | |||||
| # affiche :: 4 | |||||
| x = 3 | |||||
| x += 1 | |||||
| print(x) | |||||
| # affiche :: 4 | |||||
| @@ -0,0 +1,72 @@ | |||||
| Chapitre 4 - Booléens et conditions | |||||
| =================================== | |||||
| En Python, les variables ``True`` et ``False`` sont toujours définies | |||||
| et servent à représenter une valeur vraie ou fausse. | |||||
| (Notez qu'elles commencent par une majuscule) | |||||
| Assignation | |||||
| ----------- | |||||
| On peut assigner des variables à True ou False:: | |||||
| la_terre_est_plate = False | |||||
| python_c_est_genial = True | |||||
| Comparaisons | |||||
| ------------ | |||||
| Certaines opérations renvoient des booléens: | |||||
| +------+-----------------------------+ | |||||
| |``=`` | égal | | |||||
| +------+-----------------------------+ | |||||
| |``!=``| différent | | |||||
| +------+-----------------------------+ | |||||
| |``>`` | strictement supérieur | | |||||
| +------+-----------------------------+ | |||||
| |``>=``| supérieur ou égal | | |||||
| +------+-----------------------------+ | |||||
| |``<`` | strictement inférieur | | |||||
| +------+-----------------------------+ | |||||
| |``<=``| inférieur | | |||||
| +------+-----------------------------+ | |||||
| Par example:: | |||||
| a = 2 | |||||
| b = 3 | |||||
| print(a > b) | |||||
| # affiche: False | |||||
| print(2 + 2 == 4) | |||||
| # affiche: True | |||||
| .. warning:: | |||||
| Ne pas confondre: ``==`` pour la comparaison et ``=`` pour l'assignation | |||||
| Enfin, on peut écrire des encadrements:: | |||||
| a = 3 | |||||
| print(2 <= a < 4) | |||||
| # affiche: True | |||||
| not | |||||
| --- | |||||
| Enfin, on peut utiliser ``not`` pour inverser une condition:: | |||||
| a = 3 | |||||
| if not a == 4: | |||||
| print("a est différent de 4") | |||||
| # affiche: a est différent de 4 | |||||
| la_terre_est_plate = False | |||||
| print(not la_terre_est_plate) | |||||
| # affiche: True | |||||
| @@ -1,98 +0,0 @@ | |||||
| Chapitre 4 - code source | |||||
| ======================== | |||||
| Non persistance des variables | |||||
| ------------------------------ | |||||
| .. code-block:: console | |||||
| $ python3 | |||||
| >>> a = 2 | |||||
| >>> quit() | |||||
| ``` | |||||
| .. code-block:: console | |||||
| $ python3 | |||||
| >>> a | |||||
| Traceback (most recent call last): | |||||
| File "<stdin>", line 1, in <module> | |||||
| NameError: name 'a' is not defined | |||||
| Du code dans un fichier | |||||
| ----------------------- | |||||
| Aussi appelé: "code source", ou "source". | |||||
| L'essence du logiciel libre :) | |||||
| Installation d'un éditeur de texte simple | |||||
| ------------------------------------------ | |||||
| * Linux; ``gedit``, ``kate``, ... | |||||
| * macOS: ``CotEditor`` | |||||
| * Windows: ``Notepad++`` | |||||
| J'insiste sur **simple**. Inutile d'installer un IDE pour le moment. | |||||
| Configuration | |||||
| ------------- | |||||
| * Police de caractères à chasse fixe | |||||
| * Indentation de *4 espaces* | |||||
| * Remplacer tabulation par des espaces | |||||
| * Activer la coloration syntaxique | |||||
| Notre premier fichier source | |||||
| ----------------------------- | |||||
| Insérez le code suivant dans votre éditeur de texte | |||||
| .. code-block:: python | |||||
| # Affiche un message | |||||
| print("Bonjour, monde") | |||||
| Sauvegardez dans un fichier `bonjour.py` dans `Documents/e2l/python` par exemple | |||||
| Lancer du code en ligne de commande | |||||
| ----------------------------------- | |||||
| .. code-block:: console | |||||
| cd Documents/e2l/python/ | |||||
| python3 bonjour.py | |||||
| Bonjour, monde | |||||
| * Les lignes commençant par dièse (``#``) ont été ignorées - ce sont des *commentaires*. | |||||
| * ``print()`` affiche la valeur, comme dans le REPL. | |||||
| Note importante | |||||
| --------------- | |||||
| Vous avez juste besoin: | |||||
| * d'un éditeur de texte | |||||
| * de Python3 installé | |||||
| * d'une ligne de commande | |||||
| Pas la peine d'installer quoique ce soit de plus pour le moment | |||||
| 1. *Recopiez* le code affiché dans votre éditeur, à la suite du code | |||||
| déjà écrit | |||||
| 2. Lancez le code depuis la ligne de commande | |||||
| 3. Réparez les erreurs éventuelles | |||||
| 4. Recommencez | |||||
| @@ -1,25 +1,36 @@ | |||||
| Flot de contrôle | Flot de contrôle | ||||
| ================ | ================ | ||||
| L'essence de la programmation! | |||||
| Pour l'instant, toutes les instructions que nous avons | |||||
| écrites ont été exécutée une par une et dans l'ordre | |||||
| d'apparition dans le code source. | |||||
| Modifier l'ordre d'exécution de ces lignes s'appelle modifier le flot de | |||||
| contrôle, et c'est l'essence de la programmation! | |||||
| if | if | ||||
| -- | |||||
| ++ | |||||
| .. code-block:: python | |||||
| On peut utiliser le mot ``if`` pour autoriser ou empécher | |||||
| l'éxcution du code en-dessous:: | |||||
| a = 3 | a = 3 | ||||
| b = 4 | b = 4 | ||||
| if a == b: | if a == b: | ||||
| print("a et b sont égaux") | print("a et b sont égaux") | ||||
| print("on continue") | print("on continue") | ||||
| # affiche juste | |||||
| # on continue | |||||
| La 4ème ligne n'est pas éxécutée parce la condition | |||||
| est fausse. | |||||
| Notes: | Notes: | ||||
| * deux points à la fin de la ligne | |||||
| * indentation après les deux points | |||||
| * il y a le caractère ``:`` (deux points) à la fin de la ligne | |||||
| * le code en-dessous du ``if`` commence par 4 espaces: on appelle | |||||
| cela une *indentation* | |||||
| * si la condition n'est pas vraie, rien ne se passe | * si la condition n'est pas vraie, rien ne se passe | ||||
| Notez qu'on peut mettre uniquement une variable ou une valeur | Notez qu'on peut mettre uniquement une variable ou une valeur | ||||
| @@ -27,14 +38,25 @@ après le if. Ceci ne fonctionne pas:: | |||||
| if a = 3: | if a = 3: | ||||
| print("a égale 3") | print("a égale 3") | ||||
| # affiche: SyntaxError | |||||
| On parle aussi de "bloc" si plusieurs lignes sont identées:: | |||||
| et fait une erreur de syntaxe | |||||
| a = 3 | |||||
| b = 4 | |||||
| if a == b: | |||||
| # début du bloc | |||||
| print("a et b sont égaux") | |||||
| c = 2 * a | |||||
| # fin du block | |||||
| print("on continue") | |||||
| if / else | if / else | ||||
| --------- | --------- | ||||
| .. code-block:: | |||||
| On peut utiliser le mot ``else`` après un condition en ``if`` | |||||
| pour éxécutér un bloc si la condition est fausse:: | |||||
| a = 3 | a = 3 | ||||
| b = 4 | b = 4 | ||||
| @@ -42,52 +64,58 @@ if / else | |||||
| print("a et b sont égaux") | print("a et b sont égaux") | ||||
| else: | else: | ||||
| print("a et b sont différent") | print("a et b sont différent") | ||||
| # affiche: a et b sont différents | |||||
| if / elif | if / elif | ||||
| --------- | --------- | ||||
| .. code-block:: | |||||
| On peut utiliser ``if``, ``elif`` et ``else`` pour enchaîner plusieurs | |||||
| conditions:: | |||||
| age = 23 | |||||
| if age < 10: | if age < 10: | ||||
| print("inférieur à dix") | |||||
| print("âge inférieur à dix") | |||||
| elif 10 <= age < 20: | elif 10 <= age < 20: | ||||
| print("âge entre 10 et 20") | print("âge entre 10 et 20") | ||||
| elif 20 <= age < 40: | elif 20 <= age < 40: | ||||
| print("âge entre 20 et 40") | print("âge entre 20 et 40") | ||||
| else: | else: | ||||
| print("âge supérieur à 40") | print("âge supérieur à 40") | ||||
| On peut mettre autont de `elif` qu'on veut! | |||||
| Le derier `else` s'éxécute en dernier | |||||
| # affiche: âge entre 20 et 40 | |||||
| while | while | ||||
| ----- | ----- | ||||
| Répéter tant qu'une condition est vraie:: | |||||
| On peut utiliser ``while`` pour répéter un bloc tant qu'une condition | |||||
| est vraie:: | |||||
| i = 0 | i = 0 | ||||
| while i < 3: | while i < 3: | ||||
| print(i) | print(i) | ||||
| i = i + 1 | i = i + 1 | ||||
| .. code-block:: console | |||||
| .. code-block:: text | |||||
| 0 | 0 | ||||
| 1 | 1 | ||||
| 2 | 2 | ||||
| Notez que la variable ``i`` passe par plusieurs valeurs différentes. | |||||
| Notre première boucle infinie | |||||
| ----------------------------- | |||||
| Boucle infinie | |||||
| -------------- | |||||
| .. code-block:: | |||||
| On parle de *boucle infinie* si la condition ne devient jamais fausse:: | |||||
| while True: | while True: | ||||
| print("spam!") | print("spam!") | ||||
| CTRL-C pour interrompre | |||||
| Dans ce cas, il faut appuyer sur ``CTRL-C`` pour interrompre | |||||
| le programme. | |||||
| Notez ici qu'on a mis directement la valeur ``True``, et non une comparaison. | |||||
| Combiner while et if | Combiner while et if | ||||
| @@ -11,15 +11,23 @@ Définition:: | |||||
| * avec `def` | * avec `def` | ||||
| * avec un `:` à la fin et un *bloc indenté* (appelé le "corps") | |||||
| * avec un `:` à la fin et un *bloc indenté* (appelé *le corps de la fonction*). | |||||
| Appel:: | Appel:: | ||||
| >>> dire_bonjour() | |||||
| Bonjour | |||||
| dire_bonjour() | |||||
| * avec le nom de la fonction et des parenthèses | * avec le nom de la fonction et des parenthèses | ||||
| Example complet:: | |||||
| def dire_bonjour(): | |||||
| print("Bonjour") | |||||
| bonjour() | |||||
| # Affiche: bonjour' | |||||
| Le pouvoir des fonctions | Le pouvoir des fonctions | ||||
| ------------------------ | ------------------------ | ||||
| @@ -35,6 +43,7 @@ programmation. | |||||
| Fonction avec un argument | Fonction avec un argument | ||||
| -------------------------- | |||||
| Définition: avec l'argument à l'intérieur des parenthèses:: | Définition: avec l'argument à l'intérieur des parenthèses:: | ||||
| @@ -43,17 +52,10 @@ Définition: avec l'argument à l'intérieur des parenthèses:: | |||||
| Appel: en passant une variable ou une valeur dans les parenthèses:: | Appel: en passant une variable ou une valeur dans les parenthèses:: | ||||
| >>> dire_bonjour("Germaine") | |||||
| Bonjour Germaine | |||||
| >>> prénom_de_charlotte = "Charlotte" | |||||
| >>> dire_bonjour(prénom_de_charlotte) | |||||
| Bonjour Charlotte | |||||
| Exécution d'une fonction | |||||
| ------------------------ | |||||
| dire_bonjour("Germaine") | |||||
| C'est exatement comme si on assignait les arguments de la fonction avant d'éxécuter le code | |||||
| L'éxécution de l'appel à une foctionne exactement comme si on assignait | |||||
| les arguments de la fonction avant d'éxécuter le code | |||||
| dans le corps:: | dans le corps:: | ||||
| # Ceci: | # Ceci: | ||||
| @@ -65,3 +67,16 @@ dans le corps:: | |||||
| # Lui-même équivalent à: | # Lui-même équivalent à: | ||||
| print("Bonjour " + "Dimitri") | print("Bonjour " + "Dimitri") | ||||
| Example complet:: | |||||
| def dire_bonjour(prénom): | |||||
| print("Bonjour " + prénom) | |||||
| dire_bonjour("Germaine") | |||||
| # affiche: Bonjour Germaine | |||||
| prénom_de_charlotte = "Charlotte" | |||||
| dire_bonjour(prénom_de_charlotte) | |||||
| # affiche: Bonjour Charlotte | |||||
| @@ -22,8 +22,8 @@ Les variables en dehors des fonctions sont disponibles partout:: | |||||
| Une variable peut avoir en "cacher" une autre si elle a une portée différente:: | Une variable peut avoir en "cacher" une autre si elle a une portée différente:: | ||||
| def dire_bonjour(prénom): | def dire_bonjour(prénom): | ||||
| print("Bonjour " + prénom) # portée: uniquement dans | |||||
| # le corps dire_bonjour | |||||
| print("Bonjour " + prénom) # portée: uniquement dans | |||||
| # le corps dire_bonjour | |||||
| prénom = "Dimitri" # portée: dans tout le programme | |||||
| prénom = "Dimitri" # portée: dans tout le programme | |||||
| dire_bonjour(prénom) # Ok | dire_bonjour(prénom) # Ok | ||||
| @@ -11,9 +11,11 @@ On peut aussi mettre des valeurs par défaut:: | |||||
| Appel:: | Appel:: | ||||
| >>> dire_bonjour("Thomas", enthousiaste=True) | |||||
| Bonjour Thomas! | |||||
| >>> dire_bonjour("Thomas", enthousiaste=False) | |||||
| Bonjour Thomas | |||||
| >>> dire_bonjour("Thomas") | |||||
| Bonjour Thomas | |||||
| dire_bonjour("Thomas", enthousiaste=True) | |||||
| # affiche: Bonjour Thomas! | |||||
| dire_bonjour("Thomas", enthousiaste=False) | |||||
| # affiche: Bonjour Thomas | |||||
| dire_bonjour("Thomas") | |||||
| # affiche: Bonjour Thomas | |||||
| @@ -18,19 +18,31 @@ On peut passer autant d'arguments qu'on veut à ``print`` et: | |||||
| * Il les sépare par des espaces | * Il les sépare par des espaces | ||||
| * Ajoute un retour à la ligne à la fin:: | * Ajoute un retour à la ligne à la fin:: | ||||
| >>> prénom = "Charlotte" | |||||
| prénom = "Charlotte" | |||||
| print("Bonjour", pŕenom) | print("Bonjour", pŕenom) | ||||
| print("Ça va ?") | |||||
| .. code-block:: text | |||||
| Bonjour Charlotte | Bonjour Charlotte | ||||
| Ça va ? | |||||
| On peut demander à `print` de changer son séparateur:: | On peut demander à `print` de changer son séparateur:: | ||||
| >>> a = "chauve" | |||||
| >>> b = "souris" | |||||
| >>> print(a, b, sep="-") | |||||
| a = "chauve" | |||||
| b = "souris" | |||||
| print(a, b, sep="-") | |||||
| .. code-block:: text | |||||
| chauve-souris | chauve-souris | ||||
| Ou de changer le caractère de fin:: | Ou de changer le caractère de fin:: | ||||
| >>> print("Ceci tient", end="") | |||||
| >>> print("sur une seule ligne") | |||||
| Ceci tient sur une seule ligne | |||||
| print("Ceci tient", end="") | |||||
| print("sur une seule ligne") | |||||
| .. code-block:: text | |||||
| Ceci tient sur une seule ligne | |||||
| @@ -26,9 +26,17 @@ corps de la fonction:: | |||||
| return | return | ||||
| print("Heureux de faire votre connaissance") | print("Heureux de faire votre connaissance") | ||||
| >>> dire_bonjour("Dimitri", première_fois=True) | |||||
| dire_bonjour("Dimitri", première_fois=True) | |||||
| .. code-block:: text | |||||
| Bonjour Dimitri | Bonjour Dimitri | ||||
| Heureux de faire votre connaissance | Heureux de faire votre connaissance | ||||
| >>> dire_bonjour("Dimitri", première_fois=False) | |||||
| .. code-block:: python | |||||
| dire_bonjour("Dimitri", première_fois=False) | |||||
| .. code-block:: text | |||||
| Bonjour Dimitri | Bonjour Dimitri | ||||
| @@ -33,41 +33,48 @@ Connaître la taille d'une liste | |||||
| Avec ``len()`` - encore une fonction native:: | Avec ``len()`` - encore une fonction native:: | ||||
| >>> liste_vide = [] | |||||
| >>> len(liste_vide) | |||||
| 0 | |||||
| >>> trois_entiers = [1, 2, 3] | |||||
| >>> len(trois_entiers) | |||||
| 3 | |||||
| liste_vide = [] | |||||
| taille = len(liste_vide) | |||||
| print(taille) | |||||
| # affiche: 0 | |||||
| trois_entiers = [1, 2, 3] | |||||
| taille = len(trois_entiers) | |||||
| print(taille) | |||||
| # affiche: 3 | |||||
| Concaténation de listes | Concaténation de listes | ||||
| ----------------------- | ----------------------- | ||||
| Avec ``+``:: | Avec ``+``:: | ||||
| >>> prénoms = ["Alice", "Bob"] | |||||
| >>> prénoms += ["Charlie", "Eve"] | |||||
| >>> prénoms | |||||
| ['Alice', 'Bob', "Charlie", 'Eve'] | |||||
| prénoms = ["Alice", "Bob"] | |||||
| prénoms += ["Charlie", "Eve"] | |||||
| print(prénoms) | |||||
| # affiche: ['Alice', 'Bob', "Charlie", 'Eve'] | |||||
| On ne peut concaténer des listes que avec d'autres listes:: | On ne peut concaténer des listes que avec d'autres listes:: | ||||
| >>> scores = [1, 2, 3] | |||||
| >>> scores += 4 # TypeError | |||||
| >>> scores += [4] # OK | |||||
| scores = [1, 2, 3] | |||||
| scores += 4 | |||||
| # erreur | |||||
| scores += [4] | |||||
| print(scores) | |||||
| # affiche: [1,2,3,4] | |||||
| Test d'appartenance | Test d'appartenance | ||||
| ------------------- | ------------------- | ||||
| Avec ``in``:: | Avec ``in``:: | ||||
| >>> prénoms = ["Alice", "Bob"] | |||||
| >>> "Alice" in prénoms | |||||
| True | |||||
| prénoms = ["Alice", "Bob"] | |||||
| print("Alice" in prénoms) | |||||
| # affiche: True | |||||
| >>> prénoms = ["Alice", "Bob"] | |||||
| >>> "Charlie" in prénoms | |||||
| False | |||||
| prénoms = ["Alice", "Bob"] | |||||
| print("Charlie" in prénoms) | |||||
| # affiche: False | |||||
| Itérer sur les élements d'une liste | Itérer sur les élements d'une liste | ||||
| ------------------------------------ | ------------------------------------ | ||||
| @@ -80,35 +87,43 @@ Avec ``for ... in``:: | |||||
| # élément de la liste | # élément de la liste | ||||
| print("Bonjour", prénom) | print("Bonjour", prénom) | ||||
| .. code-block:: text | |||||
| Bonjour Alice | Bonjour Alice | ||||
| Bonjour Bob | Bonjour Bob | ||||
| Bonjour Charlie | Bonjour Charlie | ||||
| ## Indéxer une liste | |||||
| Indéxer une liste | |||||
| ------------------ | |||||
| * Avec `[]` et un entier | |||||
| * Avec ``[]`` et un entier | |||||
| * Les index valides vont de 0 à `n-1` où `n` est la | |||||
| * Les index valides vont de 0 à ``n-1`` où ``n`` est la | |||||
| taille de la liste:: | taille de la liste:: | ||||
| >>> fruits = ["pomme", "orange", "poire"] | |||||
| >>> fruits[0] | |||||
| "pomme" | |||||
| >>> fruits[1] | |||||
| "orange" | |||||
| >>> list[2] | |||||
| "poire" | |||||
| >>> fruits[3] # IndexError | |||||
| fruits = ["pomme", "orange", "poire"] | |||||
| print(fruits[0]) | |||||
| # affiche: "pomme" | |||||
| print(fruits[1]) | |||||
| # affiche: "orange" | |||||
| print(list[2]) | |||||
| # affiche: "poire" | |||||
| fruits[3] | |||||
| # erreur: IndexError | |||||
| Modifier une liste | Modifier une liste | ||||
| ------------------- | ------------------- | ||||
| Encore une assignation:: | Encore une assignation:: | ||||
| >>> fruits = ["pomme", "orange", "poire"] | |||||
| >>> fruits[0] = "abricot" | |||||
| >>> fruits | |||||
| ["abricot", "orange", "poire"] | |||||
| fruits = ["pomme", "orange", "poire"] | |||||
| fruits[0] = "abricot" | |||||
| print(fruits) | |||||
| # affiche: ["abricot", "orange", "poire"] | |||||
| Les strings sont aussi des listes (presque) | Les strings sont aussi des listes (presque) | ||||
| -------------------------------------------- | -------------------------------------------- | ||||
| @@ -128,17 +143,45 @@ On peut itérer sur les caractères d'une string:: | |||||
| On peut tester si un caractère est présent:: | On peut tester si un caractère est présent:: | ||||
| >>> "e" in "vache" | |||||
| True | |||||
| >>> "x" in "vache" | |||||
| False | |||||
| print("e" in "vache") | |||||
| # affiche: True | |||||
| print(x" in "vache") | |||||
| # affiche: False | |||||
| Mais on neut peut pas modifier une string:: | Mais on neut peut pas modifier une string:: | ||||
| >>> prénom = "Charlotte" | |||||
| >>> prénom[0] | |||||
| "C" | |||||
| >>> prénom[3] | |||||
| "r" | |||||
| >>> prénom[0] = "X" # TypeError | |||||
| prénom = "Charlotte" | |||||
| l = prénom[0] | |||||
| print(l) | |||||
| # affiche: "C" | |||||
| l = prénom[3] | |||||
| print(l) | |||||
| # affiche: "r" | |||||
| prénom[0] = "X" | |||||
| # erreur: TypeError | |||||
| Falsy et truthy | |||||
| ---------------- | |||||
| En réalité on peut mettre autre chose qu'une comparaison ou une variable booléenne après le if. | |||||
| Si on met une liste vide, ``if`` se comportera comme si on avait mis une valeur fausse, et si | |||||
| la liste n'est pas vide , ``if`` se comportera comme si on avait mis une valeur vraie.:: | |||||
| ma_liste = [1, 2, 3] | |||||
| if ma_liste: | |||||
| print("ma_liste n'est pas vide") | |||||
| # affiche: ma_liste n'est pas vide | |||||
| mon_autre_liste = [] | |||||
| if not mon_autre_liste: | |||||
| print("mon_autre_liste est vide") | |||||
| # affiche: mon_autre_liste est vide | |||||
| On dit que les listes vides sont *Falsy* et les listes non-vides *Truthy* | |||||
| @@ -8,17 +8,6 @@ Définition | |||||
| Un peu comme ``True`` et ``False`` qui sont deux valeurs qui servent à représenter tous les booléens. | Un peu comme ``True`` et ``False`` qui sont deux valeurs qui servent à représenter tous les booléens. | ||||
| Représenter l'absence | |||||
| ---------------------- | |||||
| L'interpréteur intéractif n'affiche rien quand la valeur est None:: | |||||
| >>> a = 42 | |||||
| >>> a | |||||
| 42 | |||||
| >>> b = None | |||||
| >>> b | |||||
| Retourner None | Retourner None | ||||
| ---------------- | ---------------- | ||||
| @@ -26,11 +15,12 @@ En réalité, *toutes* les fonctions pythons retournent *quelque chose*, même q | |||||
| elle ne contiennent pas le mot-clé ``return``.:: | elle ne contiennent pas le mot-clé ``return``.:: | ||||
| def ne_renvoie_rien(): | def ne_renvoie_rien(): | ||||
| print("je ne fais qu'afficher quelque chose") | |||||
| x = 2 | |||||
| >>> resultat = ne_renvoie_rien() | |||||
| "je ne fais qu'afficher quelque chose" | |||||
| >>> resultat | |||||
| resultat = ne_renvoie_rien() | |||||
| print(resultat) | |||||
| # affiche: None | |||||
| Opérations avec None | Opérations avec None | ||||
| --------------------- | --------------------- | ||||
| @@ -38,17 +28,26 @@ Opérations avec None | |||||
| La plupart des fonctions que nous avons vues échouent si on leur passe ``None`` | La plupart des fonctions que nous avons vues échouent si on leur passe ``None`` | ||||
| en argument:: | en argument:: | ||||
| >>> len(None) | |||||
| TypeError: object of type 'NoneType' has no len() | |||||
| >>> None < 3 | |||||
| TypeError: '<' not supported between instances of | |||||
| 'NoneType' and 'int' | |||||
| >>> int(None) | |||||
| TypeError: int() argument must be a string, | |||||
| a bytes-like object or a number, | |||||
| not 'NoneType' | |||||
| >>> str(None) | |||||
| 'None' | |||||
| x = len(None) | |||||
| # erreur: TypeError | |||||
| x = None < 3 | |||||
| # erreur: TypeError | |||||
| x = int(None) | |||||
| # erreur: TypeError | |||||
| Mais ``str`` fonctionne:: | |||||
| x = str(None) | |||||
| print(x) | |||||
| # affiche: 'None' | |||||
| On peut vérifier si une variable vaut ``None`` avec ``is None``:: | |||||
| x = ne_renvoie_rien() | |||||
| print(x is None) | |||||
| # affiche: True | |||||
| Example d'utilisation | Example d'utilisation | ||||
| ---------------------- | ---------------------- | ||||
| @@ -61,20 +60,10 @@ Example d'utilisation | |||||
| return element | return element | ||||
| return None | return None | ||||
| >>> trouve_dans_liste(2, [1, 2, 3]) | |||||
| 2 | |||||
| >>> trouve_dans_liste(False, [True, False]) | |||||
| False | |||||
| >>> trouve_dans_liste(1, [3, 4]) | |||||
| None est Falsy, et on peut vérifier si une variable vaut ``None`` avec ``is None``:: | |||||
| x = trouve_dans_liste(2, [1, 2, 3]) | |||||
| print(x) | |||||
| # affiche: 2 | |||||
| # hypothèse: `ma_valeur` n'est pas None | |||||
| mon_element = trouve_dans_liste(ma_valeur, ma_liste) | |||||
| if mon_element is None: | |||||
| print("élément absent de la liste") | |||||
| if not mon_element: | |||||
| # Peut-être que l'élément n'était pas dans la liste, | |||||
| # ou peut-être y était-il, mais avec une valeur falsy | |||||
| ... | |||||
| x = trouve_dans_liste(1, [3, 4]) | |||||
| print(x) | |||||
| # affiche: None | |||||
| @@ -31,49 +31,57 @@ Accès aux valeurs | |||||
| Avec ``[]``, comme pour les listes, mais avec une *clé* à la place d'un *index*:: | Avec ``[]``, comme pour les listes, mais avec une *clé* à la place d'un *index*:: | ||||
| >>> scores = {"john": 10, "bob": 42} | |||||
| >>> scores["john"] | |||||
| 10 | |||||
| >>> scores["bob"] | |||||
| 42 | |||||
| >>> scores["charlie"] | |||||
| KeyError | |||||
| scores = {"john": 10, "bob": 42} | |||||
| print(scores["john"]) | |||||
| # affiche: 10 | |||||
| print(scores["bob"]) | |||||
| # affiche: 42 | |||||
| print(scores["charlie"]) | |||||
| # erreur: KeyError | |||||
| Test d'appartenance | Test d'appartenance | ||||
| --------------------- | --------------------- | ||||
| Avec ``in``, comme le listes:: | Avec ``in``, comme le listes:: | ||||
| >>> scores = {"john": 10, "bob": 42} | |||||
| >>> "charlie" in scores | |||||
| False | |||||
| scores = {"john": 10, "bob": 42} | |||||
| print("charlie" in scores) | |||||
| # affiche: False | |||||
| Modifier la valeur d'une clé | Modifier la valeur d'une clé | ||||
| ----------------------------- | ----------------------------- | ||||
| Comme pour les listes, avec une assignation:: | Comme pour les listes, avec une assignation:: | ||||
| >>> scores = {"john": 10, "bob": 42} | |||||
| >>> scores["john"] = 20 | |||||
| >>> scores | |||||
| {"john": 20, "bob": 42} | |||||
| scores = {"john": 10, "bob": 42} | |||||
| scores["john"] = 20 | |||||
| print(scores) | |||||
| # affiche: {"john": 20, "bob": 42} | |||||
| Créer une nouvelle clé | Créer une nouvelle clé | ||||
| ----------------------- | ----------------------- | ||||
| Même méchanisme que pour la modification des clés existantes:: | |||||
| Même mécanisme que pour la modification des clés existantes:: | |||||
| scores = {"john": 10, "bob": 42} | |||||
| scores["charlie"] = 30 | |||||
| print(scores) | |||||
| # affiche: {"john": 20, "bob": 42, "charlie": 30} | |||||
| >>> scores = {"john": 10, "bob": 42} | |||||
| >>> scores["charlie"] = 30 | |||||
| >>> scores | |||||
| {"john": 20, "bob": 42, "charlie": 30} | |||||
| *rappel*: ceci ne fonctionne pas avec les listes: on ne peut | |||||
| pas "créer" de nouveaux éléments dans la liste juste | |||||
| avec un index:: | |||||
| *rappel*: ceci ne fonctionne pas avec les listes!:: | |||||
| >>> ma_liste = ["a", "b"] | |||||
| >>> ma_liste[1] = "c" # ok | |||||
| ["a", "c"] | |||||
| >>> ma_liste[3] = "d" | |||||
| IndexError | |||||
| ma_liste = ["a", "b"] | |||||
| ma_liste[1] = "c" | |||||
| print(ma_liste) | |||||
| # affiche: ["a", "c"] | |||||
| ma_liste[3] = "d" | |||||
| # erreur: IndexError | |||||
| Itérer sur les clés | Itérer sur les clés | ||||
| ------------------- | ------------------- | ||||
| @@ -84,8 +92,14 @@ Avec ``for ... in ...``, comme pour les listes:: | |||||
| for nom in scores: | for nom in scores: | ||||
| # `nom` est assigné à "john" puis "bob" | # `nom` est assigné à "john" puis "bob" | ||||
| score_associé_au_nom = scores[nom] | score_associé_au_nom = scores[nom] | ||||
| # score_associé_au_nom est assigné à '10' puis '42' | |||||
| print(nom, score_associé_au_nom) | print(nom, score_associé_au_nom) | ||||
| .. code-block:: | |||||
| john 10 | |||||
| bob 42 | |||||
| del | del | ||||
| --- | --- | ||||
| @@ -94,83 +108,31 @@ Détruire une clé | |||||
| Avec ``del`` - un nouveau mot-clé:: | Avec ``del`` - un nouveau mot-clé:: | ||||
| >>> scores = {"john": 10, "bob": 42} | |||||
| >>> del scores["bob"] | |||||
| >>> scores | |||||
| {"john": 10} | |||||
| scores = {"john": 10, "bob": 42} | |||||
| del scores["bob"] | |||||
| print(scores) | |||||
| # affiche: {"john": 10} | |||||
| Détruire un élément d'une liste | Détruire un élément d'une liste | ||||
| ++++++++++++++++++++++++++++++++ | ++++++++++++++++++++++++++++++++ | ||||
| Aussi avec ``del``:: | Aussi avec ``del``:: | ||||
| >>> fruits = ["pomme", "banane", "poire"] | |||||
| >>> del fruits[1] | |||||
| >>> fruits | |||||
| ["pomme", "poire"] | |||||
| fruits = ["pomme", "banane", "poire"] | |||||
| del fruits[1] | |||||
| print(fruits) | |||||
| # affiche: ["pomme", "poire"] | |||||
| Détruire une variable | Détruire une variable | ||||
| +++++++++++++++++++++ | +++++++++++++++++++++ | ||||
| Encore et toujours ``del``:: | Encore et toujours ``del``:: | ||||
| >>> mon_entier = 42 | |||||
| >>> mon_entier += 3 | |||||
| >>> mon_entier | |||||
| 45 | |||||
| >>> del mon_entier | |||||
| >>> mon_entier == 45 | |||||
| NameError: name 'mon_entier' is not defined | |||||
| Des dictionnaires partout | |||||
| --------------------------- | |||||
| Les variables globales d'un programme Python sont dans un dictionnaire, | |||||
| accessible avec la fonction native `globals()`:: | |||||
| $ python3 | |||||
| >>> globals() | |||||
| { | |||||
| ... | |||||
| '__doc__': None, | |||||
| '__name__': '__main__', | |||||
| ... | |||||
| } | |||||
| On reparlera de `__doc__` et `__name__` un autre jour ...:: | |||||
| $ python3 | |||||
| >>> a = 42 | |||||
| >>> globals() | |||||
| { | |||||
| ... | |||||
| '__doc__': None, | |||||
| '__name__': '__main__', | |||||
| ... | |||||
| 'a': 42 | |||||
| } | |||||
| ``` | |||||
| .. code-block:: | |||||
| python | |||||
| $ python3 | |||||
| >>> a = 42 | |||||
| >>> del globals()["a"] | |||||
| >>> a | |||||
| NameError: name 'a' is not defined | |||||
| On peut accéder aux variables locales d'une fonction avec ``locals()``:: | |||||
| def ma_fonction(): | |||||
| a = 42 | |||||
| b = 3 | |||||
| c = a + b | |||||
| print(locals()) | |||||
| >>> ma_fonction() | |||||
| {'a': 42, 'b': 3, 'c': 45} | |||||
| mon_entier = 42 | |||||
| mon_entier += 3 | |||||
| print(mon_entier) | |||||
| # affiche: 45 | |||||
| En revanche, il n'est pas conseillé de modifier le dictionaire renvoyé par ``locals()`` ... | |||||
| del mon_entier | |||||
| mon_entier += 1 | |||||
| # erreur: NameError | |||||
| @@ -35,10 +35,11 @@ Accès | |||||
| Avec ``[]`` et l'index de l'élément dans le tuple:: | Avec ``[]`` et l'index de l'élément dans le tuple:: | ||||
| mon_tuple = (42, "bonjour") | mon_tuple = (42, "bonjour") | ||||
| mon_tuple[0] | |||||
| 42 | |||||
| mon_tuple[1] | |||||
| "bonjour" | |||||
| print(mon_tuple[0]) | |||||
| # affiche: 42 | |||||
| print(mon_tuple[1]) | |||||
| # affiche: "bonjour" | |||||
| Modification | Modification | ||||
| ------------ | ------------ | ||||
| @@ -47,7 +48,7 @@ Interdit:: | |||||
| mon_tuple = (42, "bonjour") | mon_tuple = (42, "bonjour") | ||||
| mon_tuple[0] = 44 | mon_tuple[0] = 44 | ||||
| TypeError: 'tuple' object does not support item assignment | |||||
| # erreur: TypeError: 'tuple' object does not support item assignment | |||||
| Test d'appartenance | Test d'appartenance | ||||
| @@ -55,26 +56,28 @@ Test d'appartenance | |||||
| Avec ``in``: | Avec ``in``: | ||||
| >>> mon_tuple = (42, 14) | |||||
| >>> 42 in mon_tuple | |||||
| True | |||||
| mon_tuple = (42, 14) | |||||
| print(42 in mon_tuple) | |||||
| # affiche: True | |||||
| print(14 in mon_tuple) | |||||
| # affiche: True | |||||
| >>> 14 in mon_tuple | |||||
| True | |||||
| >>> 13 in mon_tuple | |||||
| False | |||||
| print(13 in mon_tuple) | |||||
| # affiche: False | |||||
| Déstructuration | Déstructuration | ||||
| ---------------- | ---------------- | ||||
| Créer plusieurs variables en une seule ligne:: | Créer plusieurs variables en une seule ligne:: | ||||
| >>> couple = ("Batman", "Robin") | |||||
| >>> héros, side_kick = couple | |||||
| >>> héros | |||||
| 'Batman' | |||||
| >>> side_kick | |||||
| 'Robin' | |||||
| couple = ("Batman", "Robin") | |||||
| héros, side_kick = couple | |||||
| print(héros) | |||||
| # affiche: Batman | |||||
| print(side_kick) | |||||
| # affiche: Robin | |||||
| Quelques erreurs classiques | Quelques erreurs classiques | ||||
| @@ -82,15 +85,15 @@ Quelques erreurs classiques | |||||
| .. code-block:: python | .. code-block:: python | ||||
| >>> héros, side_kick, ennemi = couple | |||||
| ValueError (3 != 2) | |||||
| héros, side_kick, ennemi = couple | |||||
| # erreur: ValueError (3 != 2) | |||||
| >>> (héros,) = couple | |||||
| ValueError (1 != 2) | |||||
| (héros,) = couple | |||||
| # erreur: ValueError (1 != 2) | |||||
| # Gare à la virgule: | # Gare à la virgule: | ||||
| >>> héros, = couple | |||||
| ValueError (1 != 2) | |||||
| héros, = couple | |||||
| # erreur: ValueError (1 != 2) | |||||
| Pièges | Pièges | ||||
| ------ | ------ | ||||
| @@ -110,16 +113,19 @@ Pièges | |||||
| On peut aussi déstructurer des listes:: | On peut aussi déstructurer des listes:: | ||||
| >>> fruits = ["pomme", "banane", "orange"] | |||||
| >>> premier, deuxième, troisième = fruits | |||||
| >>> premier | |||||
| "pomme" | |||||
| >>> deuxième | |||||
| "banane" | |||||
| >>> troisième | |||||
| "orange" | |||||
| fruits = ["pomme", "banane", "orange"] | |||||
| premier, deuxième, troisième = fruits | |||||
| print(premier) | |||||
| # affiche: pomme | |||||
| print(deuxième) | |||||
| # affiche: banane | |||||
| print(troisième) | |||||
| # affiche: orange | |||||
| On dit aussi: unpacking | |||||
| On dit aussi: *unpacking* | |||||
| Utilisations des tuples | Utilisations des tuples | ||||
| ------------------------ | ------------------------ | ||||
| @@ -147,6 +153,6 @@ Pour retourner plusieurs valeurs:: | |||||
| v, c = tire_carte() | v, c = tire_carte() | ||||
| print(v, "de", c) | print(v, "de", c) | ||||
| # 10 de trèfle | |||||
| # affiche: 10 de trèfle | |||||
| Ce n'est pas une nouvelle syntaxe, juste de la manipulation de tuples! | Ce n'est pas une nouvelle syntaxe, juste de la manipulation de tuples! | ||||
| @@ -105,14 +105,14 @@ Le code suivant fait exactement la même chose, mais avec une ligne de moins:: | |||||
| On peut *créer* des attributs dans *n'importe quel instance*, en utilisant l'*assignation*:: | On peut *créer* des attributs dans *n'importe quel instance*, en utilisant l'*assignation*:: | ||||
| >>> mon_instance = MaClasse() | |||||
| mon_instance = MaClasse() | |||||
| # Création de l'attribut `x` dans `mon_instance` | # Création de l'attribut `x` dans `mon_instance` | ||||
| >>> mon_instance.x = 42 | |||||
| mon_instance.x = 42 | |||||
| # Accés à l'attribut `x` dans `mon_instance` | # Accés à l'attribut `x` dans `mon_instance` | ||||
| >>> mon_instance.mon_attribut | |||||
| 42 | |||||
| print(mon_instance.mon_attribut) | |||||
| # affiche: 42 | |||||
| Méthodes - définition | Méthodes - définition | ||||
| ---------------------- | ---------------------- | ||||
| @@ -135,12 +135,14 @@ la classe:: | |||||
| class MaClasse: | class MaClasse: | ||||
| def ma_méthode(self): | def ma_méthode(self): | ||||
| return 42 | return 42 | ||||
| >>> ma_méthode() | |||||
| Erreur | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.ma_méthode() | |||||
| 42 | |||||
| ma_méthode() | |||||
| # erreur: NameError | |||||
| mon_instance = MaClasse() | |||||
| résultat = mon_instance.ma_méthode() | |||||
| print(résultat) | |||||
| # affiche: 42 | |||||
| Notez qu'on ne passe *pas* d'argument quand on apelle `ma_méthode` depuis l'instance. | Notez qu'on ne passe *pas* d'argument quand on apelle `ma_méthode` depuis l'instance. | ||||
| @@ -158,10 +160,10 @@ On peut le voir en utilisant des attributs:: | |||||
| print(self.x) | print(self.x) | ||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.x = 42 | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| mon_instance = MaClasse() | |||||
| mon_instance.x = 42 | |||||
| mon_instance.affiche_attribut_x() | |||||
| # Affiche: 42 | |||||
| On peut aussi *créer* des attributs dans une méthode:: | On peut aussi *créer* des attributs dans une méthode:: | ||||
| @@ -171,13 +173,13 @@ On peut aussi *créer* des attributs dans une méthode:: | |||||
| def affiche_attribut_x(self): | def affiche_attribut_x(self): | ||||
| print(self.x) | print(self.x) | ||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| # Erreur: `mon_instance` n'a pas d'attribut `x` | |||||
| mon_instance = MaClasse() | |||||
| mon_instance.affiche_attribut_x() | |||||
| # erreur: `mon_instance` n'a pas d'attribut `x` | |||||
| >>> mon_instance.crée_attribut_x() | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| mon_instance.crée_attribut_x() | |||||
| mon_instance.affiche_attribut_x() | |||||
| # affiche: 42 | |||||
| Les méthodes peuveunt aussi prendre plusieurs arguments, en plus de ``self`` - mais ``self`` doit | Les méthodes peuveunt aussi prendre plusieurs arguments, en plus de ``self`` - mais ``self`` doit | ||||
| toujours être le premier argument. | toujours être le premier argument. | ||||
| @@ -192,10 +194,10 @@ Par example, pour créer un attribut avec une certaine valeur:: | |||||
| def affiche_attribut_x(self); | def affiche_attribut_x(self); | ||||
| print(self.x) | print(self.x) | ||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.crée_attribut_x(42) | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| mon_instance = MaClasse() | |||||
| mon_instance.crée_attribut_x(42) | |||||
| mon_instance.affiche_attribut_x() | |||||
| # affiche: 42 | |||||
| Méthodes appelant d'autres méthodes | Méthodes appelant d'autres méthodes | ||||
| ------------------------------------ | ------------------------------------ | ||||
| @@ -217,8 +219,8 @@ les unes les autres:: | |||||
| print("fin de la méthode 2") | print("fin de la méthode 2") | ||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.méthode_2() | |||||
| mon_instance = MaClasse() | |||||
| mon_instance.méthode_2() | |||||
| .. code-block:: | .. code-block:: | ||||
| @@ -246,13 +248,13 @@ On utilise souvent ``__init__`` pour créer des attributs:: | |||||
| self.x = 1 | self.x = 1 | ||||
| self.y = 2 | self.y = 2 | ||||
| >>> mon_instance = MaClasse() | |||||
| mon_instance = MaClasse() | |||||
| # __init__ est appelée automatiquement! | # __init__ est appelée automatiquement! | ||||
| >>> mon_instance.x | |||||
| 1 | |||||
| >>> mon_instance.y | |||||
| 2 | |||||
| print(mon_instance.x) | |||||
| # affiche: 1 | |||||
| print(mon_instance.y) | |||||
| # affiche: 2 | |||||
| On prend souvent les *valeurs* des attributs à créer en arguments de la méthode ``__init__``:: | On prend souvent les *valeurs* des attributs à créer en arguments de la méthode ``__init__``:: | ||||
| @@ -264,11 +266,11 @@ On prend souvent les *valeurs* des attributs à créer en arguments de la métho | |||||
| Dans ce cas, les arguments de la méthode ``__init__`` apparaissent à l'intérieur des parenthèses après le | Dans ce cas, les arguments de la méthode ``__init__`` apparaissent à l'intérieur des parenthèses après le | ||||
| nom de la classe:: | nom de la classe:: | ||||
| >>> mon_instance = MaClasse(3, 4) | |||||
| >>> mon_instance.x | |||||
| 3 | |||||
| >>> mon_instance.y | |||||
| 4 | |||||
| mon_instance = MaClasse(3, 4) | |||||
| print(mon_instance.x) | |||||
| # affiche: 3 | |||||
| print(mon_instance.y) | |||||
| # affiche: 4 | |||||
| .. note:: | .. note:: | ||||
| @@ -16,27 +16,27 @@ Importer un module | |||||
| Ou: accéder à du code provenant d'un *autre* fichier source. | Ou: accéder à du code provenant d'un *autre* fichier source. | ||||
| Imaginons un fichier `bonjour.py` contenant seulement une assignation | |||||
| Créons un fichier `bonjour.py` contenant seulement une assignation | |||||
| d'une variable `a` à l'entier 42 :: | d'une variable `a` à l'entier 42 :: | ||||
| # Dans bonjour.py | # Dans bonjour.py | ||||
| a = 42 | a = 42 | ||||
| On peut accéder à cette variable en important le module, par | |||||
| exemple depuis l'interpréteur, en utilisant le mot-clé `import` | |||||
| suivi du nom du module:: | |||||
| Comme un fichier = un module, on vient de crée un module ``bonjour`` contenant une variable ``a``. | |||||
| $ python | |||||
| >>> import bonjour | |||||
| >>> bonjour.a | |||||
| 42 | |||||
| Si maintenant on crée un fichier ``salutations.py`` dans le même répertoire, | |||||
| on peut accéder à cette variable en *important* le module:: | |||||
| Notez que pour que cela fonctionne: | |||||
| # Dans salutations.py | |||||
| import bonjour | |||||
| print(bonjour.a) | |||||
| # affiche: 42 | |||||
| * Le nom du module est écrit directement, ce n'est *pas* une | |||||
| .. note:: | |||||
| Le nom du module est écrit directement, ce n'est *pas* une | |||||
| chaîne de caractères. | chaîne de caractères. | ||||
| * Il faut lancer la commande `python` sans argument | |||||
| * Il faut la lancer depuis le répertoire qui contient `bonjour.py`. | |||||
| On voit que l'assignation de la variable `a` dans `bonjour.py` est devenue | On voit que l'assignation de la variable `a` dans `bonjour.py` est devenue | ||||
| un *attribut* du module `bonjour` lorsque `bonjour` a été importé | un *attribut* du module `bonjour` lorsque `bonjour` a été importé | ||||
| @@ -44,52 +44,26 @@ un *attribut* du module `bonjour` lorsque `bonjour` a été importé | |||||
| Si maintenant on rajoute une fonction ``dire_bonjour`` dans ``bonjour.py``:: | Si maintenant on rajoute une fonction ``dire_bonjour`` dans ``bonjour.py``:: | ||||
| # toujours dans bonjour.py | |||||
| # Dans bonjour.py | |||||
| a = 42 | a = 42 | ||||
| def dire_bonjour(): | def dire_bonjour(): | ||||
| print("Bonjour!") | print("Bonjour!") | ||||
| On peut appeler la fonction ``dire_bonjour`` depuis l'interpréteur en accédant | |||||
| à l'attribut ``dire_bonjour`` du module ``bonjour``:: | |||||
| >>> import bonjour | |||||
| >>> bonjour.dire_bonjour() | |||||
| Bonjour! | |||||
| Différence avec la commande python | |||||
| ----------------------------------- | |||||
| Notez bien que lancer l'interpréteur et taper `import bonjour` dedans n'est pas | |||||
| la même chose que lancer `python bonjour.py`. | |||||
| Dans le deuxième cas, tout le code dans `bonjour.py` est exécuté, puis la commande python | |||||
| se termine. | |||||
| Dans le cas de l'interpréteur, on peut utiliser tous les attributs du module et appeler | |||||
| les fonctions autant de fois qu'on veut:: | |||||
| >>> import bonjour | |||||
| >>> bonjour.dire_bonjour() | |||||
| Bonjour! | |||||
| >>> bonjour.dire_bonjour() | |||||
| Bonjour! | |||||
| On peut aussi modifier les valeurs des attributs:: | |||||
| >>> import bonjour | |||||
| >>> bonjour.a | |||||
| 42 | |||||
| >>> bonjour.a = 36 | |||||
| >>> bonjour.a | |||||
| 36 | |||||
| On peut appeler la fonction ``dire_bonjour`` depuis ``salutations.py`` | |||||
| en utilisant l'attribut ``dire_bonjour`` du module ``bonjour``:: | |||||
| # Dans salutations.py | |||||
| import bonjour | |||||
| bonjour.dire_bonjour() | |||||
| # affiche: Bonjour! | |||||
| Les imports ne sont faits qu'une seule fois | Les imports ne sont faits qu'une seule fois | ||||
| ------------------------------------------- | ------------------------------------------- | ||||
| Il est important de noter que le code à l'intérieur d'un | |||||
| module n'est *pas* ré-éxécuté si le module a déjà été | |||||
| importé auparavant. | |||||
| Il est important de noter que: | |||||
| * **tout** le code à l'intérieur d'un module est éxécuté lors du premier import | |||||
| * mais il n'est *pas* ré-éxécuté si le module a déjà été importé auparavant. | |||||
| On peut le voir en mettant du code dans `bonjour.py`, | On peut le voir en mettant du code dans `bonjour.py`, | ||||
| en plus des simples définitions de fonctions et assignations | en plus des simples définitions de fonctions et assignations | ||||
| @@ -97,15 +71,20 @@ de variables:: | |||||
| # Dans bonjour.py | # Dans bonjour.py | ||||
| print("Je suis le module bonjour et tu viens de m’importer") | print("Je suis le module bonjour et tu viens de m’importer") | ||||
| def dire_bonjour(): | |||||
| .... | |||||
| .. code-block:: python | |||||
| # Dans salutation.py | |||||
| import bonjour | |||||
| # affiche: Je suis le module bonjour et tu viens de m’importer | |||||
| >>> import bonjour | |||||
| Je suis le module foo et tu viens de m’importer | |||||
| >>> import bonjour | |||||
| <rien> | |||||
| import bojour | |||||
| # n'affiche rien | |||||
| Il faudra donc redémarrer l'interpréteur à chaque fois que le code dans `bonjour.py` change. | |||||
| a bibliothèque standard | |||||
| La bibliothèque standard | |||||
| ------------------------ | ------------------------ | ||||
| La bibliothèque standard est une collection de modules directement utilisables fournis à l'installation de Python. | La bibliothèque standard est une collection de modules directement utilisables fournis à l'installation de Python. | ||||
| @@ -18,16 +18,17 @@ On peut utiliser pour cela deux classes: `Chat` et `Humain`:: | |||||
| def __init__(self, nom): | def __init__(self, nom): | ||||
| self.nom = nom | self.nom = nom | ||||
| >>> chat = Chat("Monsieur Moustaches") | |||||
| >>> chat.nom | |||||
| 'Monsieur Moustaches' | |||||
| chat = Chat("Monsieur Moustaches") | |||||
| prin(chat.nom) | |||||
| # affiche: Monsieur Moustaches | |||||
| class Humain: | class Humain: | ||||
| def __init__(self, prénom): | def __init__(self, prénom): | ||||
| self.prénom = prénom | self.prénom = prénom | ||||
| >>> alice = Humain(prénom="Alice") | |||||
| >>> alice.prénom | |||||
| "Alice" | |||||
| alice = Humain(prénom="Alice") | |||||
| print(alice.prénom) | |||||
| # affiche: Alice | |||||
| Maintenant on veut que les humains puissent adopter des chats. | Maintenant on veut que les humains puissent adopter des chats. | ||||
| Pour cela, on peut rajouter la méthode ``adopte`` dans la classe | Pour cela, on peut rajouter la méthode ``adopte`` dans la classe | ||||
| @@ -43,10 +44,10 @@ classe ``Chat``:: | |||||
| def adopte(self, chat): | def adopte(self, chat): | ||||
| print(self.prénom, "adopte un chat") | print(self.prénom, "adopte un chat") | ||||
| >>> boule_de_poils = Chat("Boule de Poils") | |||||
| >>> alice = Humain("Alice") | |||||
| >>> alice.adopte(boule_de_poils) | |||||
| "Alice adopte un chat" | |||||
| boule_de_poils = Chat("Boule de Poils") | |||||
| alice = Humain("Alice") | |||||
| alice.adopte(boule_de_poils) | |||||
| # affiche: "Alice adopte un chat" | |||||
| On peut accéder au nom du chat depuis la méthode ``adopte``, | On peut accéder au nom du chat depuis la méthode ``adopte``, | ||||
| en utilisant la syntaxe ``nom.attribut`` vue précédemment:: | en utilisant la syntaxe ``nom.attribut`` vue précédemment:: | ||||
| @@ -58,10 +59,10 @@ en utilisant la syntaxe ``nom.attribut`` vue précédemment:: | |||||
| def adopte(self, chat): | def adopte(self, chat): | ||||
| print(self.prénom, "adopte", chat.nom) | print(self.prénom, "adopte", chat.nom) | ||||
| >>> boule_de_poils = Chat("Boule de Poils") | |||||
| >>> alice = Humain("Alice") | |||||
| >>> alice.adopte(boule_de_poils) | |||||
| "Alice adopte Boule de Poils" | |||||
| boule_de_poils = Chat("Boule de Poils") | |||||
| alice = Humain("Alice") | |||||
| alice.adopte(boule_de_poils) | |||||
| # affiche: Alice adopte Boule de Poils | |||||
| Couplage | Couplage | ||||
| -------- | -------- | ||||
| @@ -1,176 +0,0 @@ | |||||
| Rappels | |||||
| ======= | |||||
| // TODO: drop? | |||||
| .. note:: | |||||
| ceci est surtout un rappel du chapitre 11. N'hésitez pas à vous y | |||||
| reporter si les exemples de code ne vous paraissent pas clairs. | |||||
| Classes vides | |||||
| ------------- | |||||
| Définition:: | |||||
| class MaClasse: | |||||
| pass | |||||
| Instanciation:: | |||||
| instance_1 = MaClasse() | |||||
| Attributs | |||||
| --------- | |||||
| Un attribut est une variable *à l'intérieur* d'autre chose (par exemple une instance de classe). | |||||
| La syntaxe consiste en l'instance à gauche et l'attribut à droite après un point:: | |||||
| >>> mon_instance = MaClasse() | |||||
| # création de l'attribut `x` dans mon_instance: | |||||
| >>> mon_instance.x = 42 | |||||
| # accès à l'attribut `x` dans mon_instance: | |||||
| >>> mon_instance.x | |||||
| 42 | |||||
| Méthodes | |||||
| -------- | |||||
| Une méthode est une fonction définie à l'intérieur d'une classe: | |||||
| Définition:: | |||||
| class MaClasse: | |||||
| def ma_méthode(self): | |||||
| return 42 | |||||
| Les méthodes sont des attributs des instances de classes:: | |||||
| class MaClasse: | |||||
| def ma_méthode(self): | |||||
| return 42 | |||||
| >>> ma_méthode() | |||||
| Erreur | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.ma_méthode() | |||||
| 42 | |||||
| self | |||||
| ---- | |||||
| `self` *prend la valeur de l'instance courante* quand la méthode est appelée.:: | |||||
| class MaClasse: | |||||
| def affiche_attribut_x(self): | |||||
| print(self.x) | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.x = 42 | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| On peut aussi *créer* des attributs dans une méthode:: | |||||
| class MaClasse: | |||||
| def crée_attribut_x(self): | |||||
| self.x = 42 | |||||
| def affiche_attribut_x(self): | |||||
| print(self.x) | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| # Erreur: `mon_instance` n'a pas d'attribut `x` | |||||
| >>> mon_instance.crée_attribut_x() | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| Méthodes avec arguments | |||||
| ------------------------ | |||||
| .. code-block:: | |||||
| class MaClasse | |||||
| def crée_attribut_x(self, valeur_de_x): | |||||
| self.x = valeur_de_x | |||||
| def affiche_attribut_x(self); | |||||
| print(self.x) | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.crée_attribut_x(42) | |||||
| >>> mon_instance.affiche_attribut_x() | |||||
| 42 | |||||
| Méthodes appelant d'autres méthodes | |||||
| ------------------------------------ | |||||
| .. code-block:: | |||||
| class MaClasse: | |||||
| def méthode_1(self): | |||||
| print("démarrage de la méthode 1") | |||||
| print("la méthode 1 affiche bonjour") | |||||
| print("bonjour") | |||||
| print("fin de la méthode 1") | |||||
| def méthode_2(self): | |||||
| print("la méthode 2 appelle la méthode 1") | |||||
| self.méthode_1() | |||||
| print("fin de la méthode 2") | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.méthode_2() | |||||
| .. code-block:: | |||||
| la méthode 2 appelle la méthode 1 | |||||
| démarrage de la méthode 1 | |||||
| la méthode 1 affiche bonjour | |||||
| bonjour | |||||
| fin de la méthode 1 | |||||
| fin de la méthode 2 | |||||
| Constructeur sans arguments | |||||
| --------------------------- | |||||
| Un constructeur en Python désigne la méthode nomée ``__init__``, | |||||
| quand celle-ci existe. | |||||
| La méthode ``__init__`` est appelée automatiquement quand la | |||||
| classe est instanciée:: | |||||
| class MaClasse: | |||||
| def __init__(self): | |||||
| self.x = 1 | |||||
| self.y = 2 | |||||
| >>> mon_instance = MaClasse() | |||||
| >>> mon_instance.x | |||||
| 1 | |||||
| >>> mon_instance.y | |||||
| 2 | |||||
| Constructeur avec arguments | |||||
| ---------------------------- | |||||
| La méthode ``__init__`` peut avoir des arguments, | |||||
| dans ce cas, ceux ci doivent être fournis | |||||
| lors de l'instanciation:: | |||||
| class MaClasse: | |||||
| def __init__(self, x, y): | |||||
| self.x = x | |||||
| self.y = y | |||||
| >>> mon_instance = MaClasse(3, 4) | |||||
| >>> mon_instance.x | |||||
| 3 | |||||
| >>> mon_instance.y | |||||
| 4 | |||||
| @@ -10,20 +10,26 @@ Une classe à l'intérieur d'une autre classe. | |||||
| Dépendances entre fonctions | Dépendances entre fonctions | ||||
| ----------------------------- | ----------------------------- | ||||
| Exemple: on veut dessiner un sapin dans le terminal:: | |||||
| Exemple :: | |||||
| def main(): | |||||
| largeur = demander_largeur() | |||||
| dessine_sapin(largeur) | |||||
| def calcule_x(): | |||||
| ... | |||||
| # du code ici | |||||
| main() | |||||
| def fait_un_truc_avec_x(x): | |||||
| ... | |||||
| # du code ici | |||||
| x = calcule_x() | |||||
| fait_un_truc_avec_x(x) | |||||
| On voit que la fonction ``dessine_sapin()`` prend un argument ``largeur``, qui est retourné | |||||
| par la fonction ``demander_largeur()``. | |||||
| ``dessine_sapin()`` doit donc être appelée *après* ``demander_largeur()``. On dit que ``dessine_sapin()`` | |||||
| _dépend_ de ``demander_largeur()``. | |||||
| On voit que la fonction ``fait_un_truc_avec_x()`` prend un argument ``x``, qui est retourné | |||||
| par la fonction ``calcule_x()``. | |||||
| ``fait_un_truc_avec_x()`` doit donc être appelée *après* ``calcule_x()``. On dit que ``fait_un_truc_avec_x()`` | |||||
| *dépend* de ``calcule_x()``. | |||||
| Dépendances entre classes | Dépendances entre classes | ||||
| ------------------------- | ------------------------- | ||||
| @@ -39,8 +45,8 @@ Revoyons la classe Chat:: | |||||
| Comme le constructeur de la classe Chat prend un nom en argument, il est impossible de construire | Comme le constructeur de la classe Chat prend un nom en argument, il est impossible de construire | ||||
| des chats sans nom:: | des chats sans nom:: | ||||
| >>> chat = Chat() | |||||
| TypeError: __init__() missing 1 required positional argument: 'nom' | |||||
| chat = Chat() | |||||
| # erreur: TypeError: __init__() missing 1 required positional argument: 'nom' | |||||
| De la même façon, si on veut que tous les enfants aient un chat (pourquoi pas, après tout), on peut | De la même façon, si on veut que tous les enfants aient un chat (pourquoi pas, après tout), on peut | ||||
| avoir une classe Enfant, dont le constructeur prend une instance de chat en plus du prénom:: | avoir une classe Enfant, dont le constructeur prend une instance de chat en plus du prénom:: | ||||
| @@ -50,11 +56,11 @@ avoir une classe Enfant, dont le constructeur prend une instance de chat en plus | |||||
| self.prénom = prénom | self.prénom = prénom | ||||
| self.chat = chat | self.chat = chat | ||||
| >>> alice = Enfant("Alice") | |||||
| TypeError: __init__() missing 1 required positional argument: 'chat' | |||||
| alice = Enfant("Alice") | |||||
| # erreur: TypeError: __init__() missing 1 required positional argument: 'chat' | |||||
| >>> boule_de_poils = Chat("Boule de Poils") | |||||
| >>> alice = Enfant("Alice", boule_de_poils) | |||||
| boule_de_poils = Chat("Boule de Poils") | |||||
| alice = Enfant("Alice", boule_de_poils) | |||||
| # OK! | # OK! | ||||
| Utilisation de la composition | Utilisation de la composition | ||||
| @@ -78,9 +84,9 @@ et ``ronronne()`` dans la classe chat:: | |||||
| self.ronronne() | self.ronronne() | ||||
| >>> boule_de_poils = Chat("Boule de Poils") | |||||
| >>> boule_de_poils.caresse() | |||||
| Boule de Poils fait "prrrrr" | |||||
| boule_de_poils = Chat("Boule de Poils") | |||||
| boule_de_poils.caresse() | |||||
| # affiche: Boule de Poils fait "prrrrr" | |||||
| Ensuite, on peut rajouter la méthode ``console()`` dans la classe Enfant, | Ensuite, on peut rajouter la méthode ``console()`` dans la classe Enfant, | ||||
| qui va: | qui va: | ||||
| @@ -95,11 +101,11 @@ qui va: | |||||
| def console(self): | def console(self): | ||||
| self.chat.caresse() | self.chat.caresse() | ||||
| >>> boule_de_poils = Chat("Boule de Poils") | |||||
| >>> alice = Enfant("Alice", boule_de_poils) | |||||
| boule_de_poils = Chat("Boule de Poils") | |||||
| alice = Enfant("Alice", boule_de_poils) | |||||
| # Alice est triste, on la console | # Alice est triste, on la console | ||||
| >>> alice.console() | |||||
| Boule de Poils fait "prrrrr" | |||||
| alice.console() | |||||
| # affiche: Boule de Poils fait "prrrrr" | |||||
| # Alice est consolée :) | # Alice est consolée :) | ||||
| On dit parfois qu'on a *délégué* l'implémentation de la méthode ``console()`` de la classe Enfant | On dit parfois qu'on a *délégué* l'implémentation de la méthode ``console()`` de la classe Enfant | ||||
| @@ -4,6 +4,5 @@ Chapitre 13 - Classes (2ème partie) | |||||
| .. toctree:: | .. toctree:: | ||||
| :maxdepth: 1 | :maxdepth: 1 | ||||
| 01-rappels | |||||
| 02-couplage | |||||
| 03-composition | |||||
| 01-couplage | |||||
| 02-composition | |||||
| @@ -4,7 +4,7 @@ sys.path | |||||
| En Python, il existe une variable ``path`` prédéfinie dans le module ``sys`` qui fonctionne de manière similaire | En Python, il existe une variable ``path`` prédéfinie dans le module ``sys`` qui fonctionne de manière similaire | ||||
| à la variable d'environnement ``PATH``. | à la variable d'environnement ``PATH``. | ||||
| Si j'essaye de l'afficher sur ma machine, voici ce que j'obtiens: | |||||
| Si j'essaye de l'afficher sur ma machine, voici ce que j'obtiens:: | |||||
| import sys | import sys | ||||
| print(sys.path) | print(sys.path) | ||||
| @@ -147,6 +147,9 @@ On peut aussi interpréter des octets comme du texte - c'est la table ASCII | |||||
| .. image:: ../img/ascii-table.png | .. image:: ../img/ascii-table.png | ||||
| La table se lit ainsi: si on veut connaître la suite de 0 et de 1 qui correspond à `B`: on lit | |||||
| les 3 premiers bits de haut en bas sur la colonne: `100`, puis les 4 bits sur la ligne: `0010`. | |||||
| Du coup 'B' en s'écrit en 7 bits: `1000010`, soit 66 en décimal, et 42 en héxadécimal | |||||
| ASCII - remarques | ASCII - remarques | ||||
| ----------------- | ----------------- | ||||
| @@ -155,20 +158,20 @@ ASCII - remarques | |||||
| * Le A est pour American | * Le A est pour American | ||||
| * Ça sert à *envoyer* du texte sur des terminaux d'où les "caractères" non-imprimables dans la liste | * Ça sert à *envoyer* du texte sur des terminaux d'où les "caractères" non-imprimables dans la liste | ||||
| * Mais c'est une convention *très* utilisée | * Mais c'est une convention *très* utilisée | ||||
| * Techniquement, on n'a besoin que de 7 bits, mais on préfère envoyer des octets | |||||
| * Un message de 4 lettres ASCII sera souvent envoyé comme 4 octets (même si seulement 7 bits sont nécessaires) | |||||
| Utiliser ASCII en Python | Utiliser ASCII en Python | ||||
| ------------------------ | ------------------------ | ||||
| Avec ``chr`` et ``ord``:: | Avec ``chr`` et ``ord``:: | ||||
| x = chr(98) | |||||
| x = chr(0x42) | |||||
| print(x) | print(x) | ||||
| # affiche: b | |||||
| # affiche: B | |||||
| x = ord('a') | |||||
| x = ord('B') | |||||
| print(x) | print(x) | ||||
| # affiche: 97 | |||||
| # affiche: 66 | |||||
| Affichage des bytearrays en Python | Affichage des bytearrays en Python | ||||
| ---------------------------------- | ---------------------------------- | ||||
| @@ -20,7 +20,7 @@ remarques. | |||||
| 01-introduction/index | 01-introduction/index | ||||
| 02-premiers-pas/index | 02-premiers-pas/index | ||||
| 03-variables-et-types/index | 03-variables-et-types/index | ||||
| 04-code-source/index | |||||
| 04-booléens/index | |||||
| 05-flot-de-controle/index | 05-flot-de-controle/index | ||||
| 06-fonctions/index | 06-fonctions/index | ||||
| 07-listes/index | 07-listes/index | ||||