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