├── README.md ├── all_in_one.md ├── append.py ├── assets ├── tp2.1.png ├── tp3.1.png ├── tp4.1.png ├── tp4.2.png ├── tp5.1.png ├── tp5.2.png ├── tp6.1.png ├── tp7.1.png ├── tp8.1.png └── tp8.2.png ├── ch08Fr.txt ├── ch09Fr.txt ├── ch10Fr.txt ├── ch11Fr.txt ├── ch12Fr.txt ├── ch13Fr.txt ├── ch14Fr.txt ├── ch15Fr.txt ├── ch16Fr.txt ├── ch17Fr.txt ├── ch18Fr.txt ├── ch19Fr.txt ├── ch20FrA.txt ├── ch20Frb.txt ├── chapter03.html ├── chapter03.md ├── chapter03.pdf ├── chapter04.html ├── chapter04.md ├── chapter04.pdf ├── chapter05.html ├── chapter05.md ├── chapter05.pdf ├── chapter06.html ├── chapter06.md ├── chapter06.pdf ├── chapter07.html ├── chapter07.md ├── chapter07.pdf ├── chapter08.html ├── chapter08.md ├── completed_upto_now.html ├── completed_upto_now.md ├── completed_upto_now.pdf ├── desktop.ini ├── mdtohtml.py ├── newf.md ├── ooo.pdf ├── script.py └── ttt.html /README.md: -------------------------------------------------------------------------------- 1 | # Think-Python-Fr 2 | Official french translation of Think Python - How To Think Like A Computer Scientist 3 | 4 | # Contributing 5 | Translating from http://greenteapress.com/thinkpython2/html/index.html . To contribute, we need to 6 | 7 | - reformat existing .txt to .md 8 | - translate the 3 sections of the preface (add them as .mds) 9 | 10 | See existing mds for conventions and styles namely 11 | 12 | use ```python 13 | 14 | for python codes 15 | 16 | at the begining of each chapter that's the md format 17 | 18 | ``` 19 | # Chapitre 4 20 | 21 | ## Cas d'étude: conception d'interface 22 |

23 | ``` 24 | 25 | 26 | 27 | # Assignments 28 | ~~~ 29 | 30 | | Chapter | Translator | Status | 31 | | ---------------|:---------------:| --------:| 32 | | preface | | | 33 | | chapter01 | @Abdur-rahmaanj | finished | 34 | | chapter02 | @Abdur-rahmaanj | finished | 35 | | chapter03 | @Abdur-rahmaanj | finished | 36 | | chapter04 | @Abdur-rahmaanj | finished | 37 | | chapter05 | @Abdur-rahmaanj | finished | 38 | | chapter06 | @Abdur-rahmaanj | finished | 39 | | chapter07 | @Abdur-rahmaanj | finished | 40 | | chapter08 | @Abdur-rahmaanj | finished | 41 | | chapter09 | @Abdur-rahmaanj | finished | 42 | | chapter10 | @Abdur-rahmaanj | finished | 43 | | chapter11 | @Abdur-rahmaanj | finished | 44 | | chapter12 | @Abdur-rahmaanj | finished | 45 | | chapter13 | @Abdur-rahmaanj | finished | 46 | | chapter14 | @Abdur-rahmaanj | finished | 47 | | chapter15 | @Abdur-rahmaanj | finished | 48 | | chapter16 | @Abdur-rahmaanj | finished | 49 | | chapter17 | @Abdur-rahmaanj | finished | 50 | | chapter18 | @Abdur-rahmaanj | finished | 51 | | chapter19 | @Abdur-rahmaanj | finished | 52 | | glossary | | | 53 | | appendix | | | 54 | 55 | # Crucial terms 56 | 57 | TODO 58 | ~~~ 59 | -------------------------------------------------------------------------------- /append.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | from os.path import isfile, join 3 | 4 | mypath = '../translated' 5 | onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))] 6 | 7 | for f in onlyfiles: 8 | with open(f, 'r', encoding="utf8") as trf: 9 | with open('newf.md', 'a', encoding="utf8") as mdf: 10 | mdf.write(trf.read()) 11 | 12 | Python Project of the Week 13 | 14 | 15 | 16 | Made an Open Inventory Mangement solution called Shopyo (shop+py+open). It's designed to be a localhost app! 17 | 18 | 19 | 20 | Months ago i was searching github, looking for a point of sales solution using Python. What pricked me was that a good many had an annoying point. Some mandatorily required Posgres as though it ships with your computer, others codebases' were a tkinter spaghetti mess, others were django-based accounting monsters ... 21 | 22 | 23 | 24 | I decided to give it a try, modelling it after a client request i once got. Made it flask-based with sqlalchemy+sqlite. You can instantly get started with no hassle, switching to something powerful when you want to (since it uses an ORM) 25 | 26 | 27 | 28 | For the UI, we used the latest, bootstrap4, fa5 and jq3. Interestingly enough, i had two shop owners try it, the usage simplicity was praised. 29 | 30 | 31 | 32 | It's still in dev and supports instant lookup. Long story short, with some programming skills, you can solve some everyday problems. And yes, no cdn, all libs are bundled so that you can use it completely offline. 33 | 34 | 35 | 36 | Github: https://github.com/Abdur-rahmaanJ/shopyo 37 | 38 | 39 | 40 | If you want to contributee, go ahead, we ❤️ it. Don't be afraid, we follow a 💯 % first-timers-friendly policy. 41 | 42 | 43 | 44 | Cedric Poilly - That's where i use web 45 | 46 | Jean Paul Fortuno - Flask XD 47 | 48 | #python -------------------------------------------------------------------------------- /assets/tp2.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp2.1.png -------------------------------------------------------------------------------- /assets/tp3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp3.1.png -------------------------------------------------------------------------------- /assets/tp4.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp4.1.png -------------------------------------------------------------------------------- /assets/tp4.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp4.2.png -------------------------------------------------------------------------------- /assets/tp5.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp5.1.png -------------------------------------------------------------------------------- /assets/tp5.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp5.2.png -------------------------------------------------------------------------------- /assets/tp6.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp6.1.png -------------------------------------------------------------------------------- /assets/tp7.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp7.1.png -------------------------------------------------------------------------------- /assets/tp8.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp8.1.png -------------------------------------------------------------------------------- /assets/tp8.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/assets/tp8.2.png -------------------------------------------------------------------------------- /ch08Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 8 2 | 3 | Strings 4 | Les chaînes ne sont pas des entiers, des flottants et des booléens. Une chaîne est une séquence, ce qui signifie qu'elle est 5 | une collection ordonnée d'autres valeurs. Dans ce chapitre, vous verrez comment accéder aux caractères 6 | qui constituent une chaîne, et vous apprendrez certaines des méthodes fournies par les chaînes. 7 | 8 | 8.1 9 | 10 | Une chaîne est une séquence 11 | 12 | Une chaîne est une séquence de caractères. Vous pouvez accéder aux personnages un par un avec le 13 | opérateur de support: 14 | 15 | >>> fruit = 'banana' 16 | >>> letter = fruit[1] 17 | La deuxième instruction sélectionne le numéro 1 du fruit et l'affecte à la lettre. 18 | L'expression entre parenthèses s'appelle un index. L'index indique quel caractère dans le 19 | séquence que vous voulez (d'où le nom). 20 | Mais vous pourriez ne pas avoir ce que vous attendez: 21 | 22 | >>> letter 23 | 'a' 24 | Pour la plupart des gens, la première lettre de «banane» est b, pas a. Mais pour les informaticiens, le 25 | index est un décalage par rapport au début de la chaîne et le décalage de la première lettre est zéro. 26 | >>> letter = fruit[0] 27 | >>> letter 28 | 'b' 29 | Donc b est la 0ème lettre ("zero-eth") de "banane", a est la 1ère lettre ("one-eth"), et n est le 2eme 30 | lettre ("two-eth"). 31 | En tant qu’index, vous pouvez utiliser une expression contenant des variables et des opérateurs: 32 | 33 | >>> i = 1 34 | >>> fruit[i] 35 | 'a' 36 | >>> fruit[i+1] 37 | 'n' 38 | 39 | 72 40 | 41 | Chapitre 8. Chaînes 42 | 43 | Mais la valeur de l'index doit être un entier. Sinon, vous obtenez: 44 | 45 | >>> letter = fruit[1.5] 46 | TypeError: string indices must be integers 47 | 48 | 8.2 49 | 50 | len 51 | 52 | len est une fonction intégrée qui renvoie le nombre de caractères d'une chaîne: 53 | >>> fruit = 'banana' 54 | >>> len(fruit) 55 | 6 56 | Pour obtenir la dernière lettre d'une chaîne, vous pourriez être tenté d'essayer quelque chose comme ceci: 57 | 58 | >>> length = len(fruit) 59 | >>> last = fruit[length] 60 | IndexError: string index out of range 61 | La raison de l’indexError est qu’il n’ya pas de lettre dans «banana» avec l’index 6. 62 | nous avons commencé à compter à zéro, les six lettres sont numérotées de 0 à 5. Pour obtenir le dernier caractère, 63 | vous devez soustraire 1 de la longueur: 64 | 65 | >>> last = fruit[length-1] 66 | >>> last 67 | 'a' 68 | Ou vous pouvez utiliser des index négatifs, qui comptent à partir de la fin de la chaîne. le 69 | expression fruit [-1] donne la dernière lettre, fruit [-2] renvoie la seconde à la dernière, et ainsi de suite. 70 | 71 | 8.3 72 | 73 | Traversal avec une boucle for 74 | 75 | De nombreux calculs impliquent le traitement d'une chaîne par caractère. Ils commencent souvent 76 | au début, sélectionnez chaque personnage à son tour, faites-lui quelque chose et continuez jusqu'à la 77 | fin. Ce modèle de traitement s'appelle une traversée. Une façon d'écrire une traversée est d'utiliser un 78 | un boucle: 79 | 80 | index = 0 81 | while index < len(fruit): 82 | letter = fruit[index] 83 | print(letter) 84 | index = index + 1 85 | Cette boucle traverse la chaîne et affiche chaque lettre sur une ligne. La condition de la boucle 86 | est index < len(fruit), donc quand index est égal à la longueur de la chaîne, la condition est 87 | false et le corps de la boucle ne s'exécute pas. Le dernier personnage accédé est celui avec le 88 | index len (fruit) -1, qui est le dernier caractère de la chaîne. 89 | En tant qu’exercice, écrivez une fonction qui prend une chaîne comme argument et affiche les lettres 90 | en arrière, un par ligne. 91 | Une autre façon d'écrire une traversée consiste à utiliser une boucle for: 92 | 93 | for letter in fruit: 94 | print(letter) 95 | 96 | 8.4. Tranches de chaîne 97 | 98 | 73 99 | fruit 100 | 101 | ’ banana’ 102 | 103 | index 0 104 | 105 | 1 106 | 107 | 2 108 | 109 | 3 110 | 111 | 4 112 | 113 | 5 114 | 115 | 6 116 | 117 | Figure 8.1: Indices de tranches. 118 | A chaque fois dans la boucle, le caractère suivant de la chaîne est assigné à la variable 119 | lettre. La boucle continue jusqu'à ce qu'il ne reste plus aucun caractère. 120 | L'exemple suivant montre comment utiliser la concaténation (ajout de chaîne) et une boucle for 121 | pour générer une série abécédaire (c'est-à-dire par ordre alphabétique). Dans le livre de Robert McCloskey's 122 | Make Way for Ducklings, les noms des canetons sont Jack, Kack, Lack, Mack, Nack, 123 | Ouack, Pack et Quack. Cette boucle génère ces noms dans l'ordre: 124 | 125 | prefixes = 'JKLMNOPQ' 126 | suffix = 'ack' 127 | for letter in prefixes: 128 | print(letter + suffix) 129 | The output is: 130 | 131 | Jack 132 | Kack 133 | Lack 134 | Mack 135 | Nack 136 | Oack 137 | Pack 138 | Qack 139 | Bien sûr, ce n'est pas tout à fait correct, car "Ouack" et "Quack" sont mal orthographiés. En tant qu'exercice, 140 | modifiez le programme pour corriger cette erreur. 141 | 142 | 8.4 143 | 144 | Tranches de chaîne 145 | 146 | Un segment d'une chaîne est appelé une tranche. La sélection d'une tranche est similaire à la sélection d'un caractère: 147 | 148 | >>> s = 'Monty Python' 149 | >>> s [0: 5] 150 | 'Monty' 151 | >>> s [6:12] 152 | 'Python' 153 | L'opérateur [n: m] renvoie la partie de la chaîne du caractère "n-eth" au "m-eth" 154 | , y compris le premier mais excluant le dernier. Ce comportement est contre-intuitif, mais 155 | il pourrait être utile d'imaginer les indices pointant entre les caractères, comme dans la figure 8.1. 156 | Si vous omettez le premier index (avant les deux points), la tranche commence au début de la chaîne. 157 | Si vous omettez le deuxième index, la tranche va à la fin de la chaîne: 158 | 159 | >>> fruit = 'banana' 160 | >>> fruit[:3] 161 | 162 | 74 163 | 164 | Chapitre 8. Chaînes 165 | 166 | 'ban' 167 | >>> fruit[3:] 168 | 'ana' 169 | Si le premier index est supérieur ou égal au second, le résultat est une chaîne vide, représentée par deux guillemets: 170 | 171 | >>> fruit = 'banana' 172 | >>> fruit[3:3] 173 | '' 174 | Une chaîne vide ne contient aucun caractère et a la longueur 0, mais à part ça, c'est la même chose 175 | comme toute autre chaîne. 176 | Poursuivant cet exemple, à votre avis, que veut dire fruit [:]? Essayez-le et voyez. 177 | 178 | 8.5 179 | 180 | Les caractères sont immuables 181 | 182 | Il est tentant d’utiliser l’opérateur [] à gauche d’une affectation, avec l’intention de 183 | changer un caractère dans une chaîne. Par exemple: 184 | 185 | >>> greeting = 'Hello, world!' 186 | >>> greeting[0] = 'J' 187 | TypeError: 'str' object does not support item assignment 188 | Le "objet" dans ce cas est la chaîne et "l'élément" est le caractère que vous avez essayé d'attribuer. 189 | Pour l'instant, un objet est la même chose qu'une valeur, mais nous affinerons cette définition ultérieurement 190 | (Section 10.10). 191 | La raison de l'erreur est que les chaînes sont immuables, ce qui signifie que vous ne pouvez pas changer un 192 | chaîne existante. Le mieux que vous puissiez faire est de créer une nouvelle chaîne qui est une variante de l'original: 193 | 194 | >>> greeting = 'Hello, world!' 195 | >>> new_greeting = 'J' + greeting[1:] 196 | >>> new_greeting 197 | 'Jello, world!' 198 | Cet exemple concatène une nouvelle première lettre sur une tranche de message d'accueil. Cela n'a aucun effet sur le 199 | chaîne originale. 200 | 201 | 8.6 202 | 203 | Recherche 204 | 205 | Que fait la fonction suivante? 206 | 207 | def find(word, letter): 208 | index = 0 209 | while index < len(word): 210 | if word[index] == letter: 211 | return index 212 | index = index + 1 213 | return -1 214 | 215 | 8.7. En boucle et compter 216 | 217 | 75 218 | 219 | En un sens, find est l'inverse de l'opérateur []. Au lieu de prendre un index et d’extraire 220 | le caractère correspondant, il prend un caractère et trouve l'index où ce caractère 221 | apparaît. Si le caractère n'est pas trouvé, la fonction renvoie -1. 222 | C'est le premier exemple que nous avons vu d'une déclaration de retour dans une boucle. Si mot [index] 223 | == lettre, la fonction sort de la boucle et revient immédiatement. 224 | Si le caractère n'apparaît pas dans la chaîne, le programme quitte la boucle normalement et renvoie -1. 225 | Ce modèle de calcul-traversant une séquence et retournant quand on trouve ce que l'on 226 | sont à la recherche-est appelé une recherche. 227 | En tant qu’exercice, modifiez la recherche pour qu’elle ait un troisième paramètre, l’index dans le mot où 228 | devrait commencer à regarder. 229 | 230 | 8.7 231 | 232 | En boucle et compter 233 | 234 | Le programme suivant compte le nombre de fois que la lettre a apparaît dans une chaîne: 235 | 236 | word = 'banana' 237 | count = 0 238 | for letter in word: 239 | if letter == 'a': 240 | count = count + 1 241 | print(count) 242 | Ce programme montre un autre modèle de calcul appelé compteur. La variable 243 | count est initialisé à 0 puis incrémenté chaque fois qu'un a est trouvé. Lorsque la boucle se termine, 244 | count contient le résultat - le nombre total de a. 245 | En guise d’exercice, encapsulez ce code dans une fonction nommée count et généralisez-le pour que 246 | il accepte la chaîne et la lettre comme arguments. 247 | Ensuite, réécrivez la fonction de sorte que, au lieu de parcourir la chaîne, elle utilise la version à trois paramètres de find de la section précédente. 248 | 249 | 8,8 250 | 251 | Méthodes de chaîne 252 | 253 | Les chaînes fournissent des méthodes permettant d'effectuer diverses opérations utiles. Une méthode est similaire 254 | à une fonction, elle prend des arguments et retourne une valeur, mais la syntaxe est différente. Pour 255 | Par exemple, la méthode upper prend une chaîne et retourne une nouvelle chaîne avec toutes les majuscules 256 | des lettres. 257 | Au lieu de la syntaxe de fonction supérieure (mot), elle utilise la syntaxe de la méthode word.upper (). 258 | 259 | >>> word = 'banana' 260 | >>> new_word = word.upper() 261 | >>> new_word 262 | 'BANANA' 263 | 264 | 76 265 | 266 | Chapitre 8. Chaînes 267 | 268 | Cette forme de notation par points spécifie le nom de la méthode, supérieure et le nom de la 269 | chaîne pour appliquer la méthode à, mot. Les parenthèses vides indiquent que cette méthode 270 | ne prend aucun argument. 271 | Un appel de méthode est appelé une invocation; dans ce cas, nous dirions que nous invoquons 272 | supérieur sur le mot. 273 | Comme il se trouve, il existe une méthode de chaîne nommée find qui est remarquablement similaire à la 274 | fonction nous avons écrit: 275 | 276 | >>> word = 'banana' 277 | >>> index = word.find('a') 278 | >>> index 279 | 1 280 | Dans cet exemple, nous invoquons find sur word et transmettons la lettre que nous recherchons en tant que paramètre. 281 | En fait, la méthode de recherche est plus générale que notre fonction; il peut trouver des sous-chaînes, pas seulement 282 | personnages: 283 | 284 | >>> word.find ('na') 285 | 2 286 | Par défaut, find commence au début de la chaîne, mais il peut prendre un deuxième argument, le 287 | index où il devrait commencer: 288 | 289 | >>> word.find ('na', 3) 290 | 4 291 | Ceci est un exemple d'un argument optionnel; find peut aussi prendre un troisième argument, l'index 292 | où il devrait s'arrêter: 293 | 294 | >>> name = 'bob' 295 | >>> name.find ('b', 1, 2) 296 | -1 297 | Cette recherche échoue car b n'apparaît pas dans la plage d'index de 1 à 2, sans inclure 2. 298 | Recherche jusqu'au, mais non compris, le deuxième index rend la recherche cohérente avec l'opérateur de 299 | tranche. 300 | 301 | 8,9 302 | 303 | L'opérateur in 304 | 305 | Le mot in est un opérateur booléen qui prend deux chaînes et renvoie True si le premier apparaît comme une sous-chaîne dans le second: 306 | 307 | >>> 'a' in 'banana' 308 | True 309 | >>> 'seed' in 'banana' 310 | False 311 | Par exemple, la fonction suivante imprime toutes les lettres de word1 qui apparaissent également dans 312 | mot2: 313 | 314 | def in_both(word1, word2): 315 | for letter in word1: 316 | if letter in word2: 317 | print(letter) 318 | 319 | 8.10. Comparaison de chaîne 320 | 321 | 77 322 | 323 | Avec des noms de variables bien choisis, Python se lit parfois comme l'anglais. Vous pouvez lire 324 | cette boucle, "pour (chaque) lettre dans (le premier) mot, si (la) lettre (apparaît) dans (le second) mot, 325 | imprimer la lettre. " 326 | Voici ce que vous obtenez si vous comparez des pommes et des oranges: 327 | 328 | >>> in_both('apples', 'oranges') 329 | a 330 | e 331 | s 332 | 333 | 8.10 334 | 335 | Comparaison de chaîne 336 | 337 | Les opérateurs relationnels travaillent sur des chaînes. Pour voir si deux chaînes sont égales: 338 | 339 | if word == 'banana': 340 | print('All right, bananas.') 341 | D'autres opérations relationnelles sont utiles pour mettre les mots en ordre alphabétique: 342 | 343 | if word < 'banana': 344 | print('Your word, ' + word + ', comes before banana.') 345 | elif word > 'banana': 346 | print('Your word, ' + word + ', comes after banana.') 347 | else: 348 | print('All right, bananas.') 349 | Python ne gère pas les lettres majuscules et minuscules de la même manière que les gens. Tous les 350 | les lettres majuscules viennent avant toutes les lettres minuscules, donc: 351 | 352 | Votre mot, ananas, vient avant la banane. 353 | Une méthode courante pour résoudre ce problème consiste à convertir des chaînes en un format standard, tel que 354 | tout en minuscule, avant d'effectuer la comparaison. Gardez cela à l'esprit au cas où vous devriez 355 | Défendez-vous contre un homme armé d'un Ananas. 356 | 357 | 8.11 358 | 359 | Le débogage 360 | 361 | Lorsque vous utilisez des indices pour parcourir les valeurs dans une séquence, il est difficile de commencer 362 | et fin du parcours à droite. Voici une fonction censée comparer deux mots 363 | et retourner True si l'un des mots est l'inverse de l'autre, mais il contient deux erreurs: 364 | 365 | def is_reverse(word1, word2): 366 | if len(word1) != len(word2): 367 | return False 368 | i = 0 369 | j = len(word2) 370 | while j > 0: 371 | if word1[i] != word2[j]: 372 | return False 373 | i = i+1 374 | 375 | 78 376 | 377 | Chapitre 8. Chaînes 378 | 379 | j = j-1 380 | return True 381 | La première instruction if vérifie si les mots ont la même longueur. Sinon, nous pouvons retourner 382 | False immédiatement Sinon, pour le reste de la fonction, on peut supposer que les mots 383 | sont la même longueur Ceci est un exemple du modèle de gardien dans la section 6.8. 384 | i et j sont des indices: i traverse mot1 en avant tandis que j traverse mot2 en arrière. Si nous 385 | trouver deux lettres qui ne correspondent pas, nous pouvons retourner False immédiatement. Si nous passons à travers le 386 | boucle entière et toutes les lettres correspondent, nous retournons True. 387 | Si nous testons cette fonction avec les mots "pots" et "stop", nous attendons la valeur de retour True, 388 | mais nous obtenons un IndexError: 389 | >>> is_reverse('pots', 'stop') 390 | ... 391 | File "reverse.py", line 15, in is_reverse 392 | if word1[i] != word2[j]: 393 | IndexError: string index out of range 394 | Pour déboguer ce genre d'erreur, je commence par imprimer les valeurs des indices immédiatement avant la ligne où l'erreur apparaît. 395 | while j > 0: 396 | print(i, j) 397 | # print here 398 | 399 | if word1[i] != word2[j]: 400 | return False 401 | i = i+1 402 | j = j-1 403 | Maintenant, lorsque je relance le programme, je reçois plus d'informations: 404 | >>> is_reverse ('pots', 'stop') 405 | 0 4 406 | ... 407 | IndexError: index de chaîne hors limites 408 | La première fois dans la boucle, la valeur de j est 4, ce qui est hors de portée pour le 409 | chaîne 'pots'. L'index du dernier caractère est 3, donc la valeur initiale de j devrait être 410 | len (word2) -1. 411 | Si je corrige cette erreur et lance à nouveau le programme, j'obtiens: 412 | >>> is_reverse ('pots', 'stop') 413 | 0 3 414 | 1 2 415 | 2 1 416 | True 417 | Cette fois, nous obtenons la bonne réponse, mais il semble que la boucle ne soit exécutée que trois fois, ce qui est 418 | méfiant. Pour avoir une meilleure idée de ce qui se passe, il est utile de dessiner un diagramme d'état. 419 | Au cours de la première itération, le cadre de is_reverse est illustré à la figure 8.2. 420 | J'ai pris une licence en organisant les variables dans le cadre et en ajoutant des lignes pointillées pour montrer 421 | que les valeurs de i et j indiquent des caractères dans word1 et word2. 422 | À partir de ce diagramme, lancez le programme sur papier en changeant les valeurs de i et j 423 | lors de chaque itération. Recherchez et corrigez la deuxième erreur dans cette fonction. 424 | 425 | 8.12. Glossaire 426 | 427 | 79 428 | word1 429 | i 430 | 431 | ’pots’ 432 | 0 433 | 434 | word2 435 | 436 | ’stop’ 437 | j 438 | 439 | 3 440 | 441 | Figure 8.2: Diagramme d'état. 442 | 443 | 8.12 444 | 445 | Glossaire 446 | 447 | objet: quelque chose auquel une variable peut se référer. Pour l'instant, vous pouvez utiliser "objet" et "valeur" 448 | indifféremment. 449 | sequence: Collection ordonnée de valeurs où chaque valeur est identifiée par un entier 450 | indice. 451 | item: Une des valeurs d'une séquence. 452 | index: valeur entière utilisée pour sélectionner un élément dans une séquence, tel qu'un caractère dans une chaîne. 453 | Dans Python, les index commencent à 0. 454 | slice: partie d'une chaîne spécifiée par une plage d'indices. 455 | Chaîne vide: Chaîne sans caractères et longueur 0, représentée par deux guillemets 456 | des notes. 457 | immutable: La propriété d'une séquence dont les éléments ne peuvent pas être modifiés. 458 | traverse: pour parcourir les éléments d'une séquence, en effectuant une opération similaire sur 459 | chaque. 460 | search: Un modèle de parcours qui s'arrête lorsqu'il trouve ce qu'il cherche. 461 | counter: variable utilisée pour compter quelque chose, généralement initialisée à zéro puis incrémentée. 462 | invocation: une instruction qui appelle une méthode. 463 | argument optionnel: argument de fonction ou de méthode non requis. 464 | 465 | 8.13 466 | 467 | Des exercices 468 | 469 | Exercice 8.1. Lisez la documentation des méthodes de chaîne à l'adresse http: // docs. python. org / 3 / 470 | bibliothèque / stdtypes. html # string-methods. Vous pourriez vouloir expérimenter avec certains d'entre eux 471 | pour vous assurer que vous comprenez comment ils fonctionnent. strip et replace sont particulièrement utiles. 472 | La documentation utilise une syntaxe qui peut être source de confusion. 473 | Par exemple, dans 474 | find (sub [, start [, end]]), les crochets indiquent des arguments facultatifs. Donc sub est requis, mais 475 | start est optionnel, et si vous incluez start, alors end est optionnel. 476 | Exercice 8.2. Il existe une méthode de chaîne appelée count qui est similaire à la fonction de la section 8.7. 477 | Lisez la documentation de cette méthode et écrivez une invocation qui compte le nombre de 478 | 'banane'. 479 | Exercice 8.3. Une tranche de chaîne peut prendre un troisième index qui spécifie la "taille de pas"; c'est-à-dire le nombre 480 | des espaces entre les caractères successifs. Un pas de 2 signifie tous les autres caractères; 3 signifie tous les 481 | troisième, etc. 482 | 483 | 80 484 | 485 | Chapitre 8. Chaînes 486 | 487 | >>> fruit = 'banana' 488 | >>> fruit[0:5:2] 489 | 'bnn' 490 | Une taille de pas de -1 traverse le mot en arrière, de sorte que la tranche [:: - 1] génère une chaîne inversée. 491 | Utilisez cet idiome pour écrire une version d'une ligne de is_palindrome à partir de l'exercice 6.3. 492 | Exercice 8.4. Les fonctions suivantes sont toutes destinées à vérifier si une chaîne contient des 493 | lettres minuscules, mais au moins certaines d'entre elles sont fausses. Pour chaque fonction, décrivez ce que la fonction 494 | fait (en supposant que le paramètre est une chaîne). 495 | 496 | def any_lowercase1(s): 497 | for c in s: 498 | if c.islower(): 499 | return True 500 | else: 501 | return False 502 | def any_lowercase2(s): 503 | for c in s: 504 | if 'c'.islower(): 505 | return 'True' 506 | else: 507 | return 'False' 508 | def any_lowercase3(s): 509 | for c in s: 510 | flag = c.islower() 511 | return flag 512 | def any_lowercase4(s): 513 | flag = False 514 | for c in s: 515 | flag = flag or c.islower() 516 | return flag 517 | def any_lowercase5(s): 518 | for c in s: 519 | if not c.islower(): 520 | return False 521 | return True 522 | Exercice 8.5. Un cryptage César est une forme de cryptage faible qui consiste à "faire tourner" chaque lettre de 523 | un nombre fixe de places. Faire pivoter une lettre signifie la déplacer dans l’alphabet 524 | au début si nécessaire, 'A' pivoté de 3 est 'D' et 'Z' tourné de 1 est 'A'. 525 | Pour faire pivoter un mot, faites pivoter chaque lettre du même montant. Par exemple, "cheer" pivoté de 7 est "jolly" 526 | et "melon" tourné de -10 est "cubed". Dans le film 2001: Odyssée de l'espace, l'ordinateur de bord 527 | est appelée HAL, qui est tournée de -1 par IBM. 528 | Ecrire une fonction appelée rotate_word qui prend une chaîne et un entier comme paramètres et renvoie 529 | une nouvelle chaîne contenant les lettres de la chaîne d'origine pivotée par la quantité donnée. 530 | Vous voudrez peut-être utiliser la fonction intégrée ord, qui convertit un caractère en code numérique, et 531 | 532 | 8.13. Des exercices 533 | 534 | 81 535 | 536 | chr, qui convertit les codes numériques en caractères. Les lettres de l'alphabet sont codées par ordre alphabétique 537 | ordre, par exemple: 538 | >>> ord ('c') - ord ('a') 539 | 2 540 | Parce que "c" est la lettre de deux éthiques de l'alphabet. Mais attention: les codes numériques pour les majuscules 541 | les lettres sont différentes. 542 | Les blagues potentiellement choquantes sur Internet sont parfois encodées dans ROT13, qui est une César 543 | cypher avec rotation 13. Si vous n'êtes pas facilement offensé, trouvez et décodez certains d'entre eux. Solution: 544 | http: // thinkpython2. com / code / rotate. py. 545 | 546 | 82 547 | 548 | Chapitre 8. Chaînes -------------------------------------------------------------------------------- /ch09Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 9 2 | 3 | Cas d'étude: jeu de mots 4 | Ce chapitre présente la deuxième cas d'étude, qui consiste à résoudre des énigmes de mots en 5 | rechercher des mots qui ont certaines propriétés. Par exemple, nous trouverons les palindromes les plus longs en anglais et rechercherons des mots dont les lettres apparaissent dans l’ordre alphabétique. Et 6 | Je présenterai un autre plan de développement de programme: réduction à un problème déjà résolu. 7 | 8 | 9.1 9 | 10 | Lecture de listes de mots 11 | 12 | Pour les exercices de ce chapitre, nous avons besoin d'une liste de mots anglais. Il y a beaucoup de mot 13 | listes disponibles sur le Web, mais celle qui convient le mieux à notre objectif est l'une des listes de mots 14 | collecté et contribué au domaine public par Grady Ward dans le cadre du projet de lexique Moby (voir http://wikipedia.org/wiki/Moby_Project). C'est une liste de 113 809 mots croisés 15 | officiels; c'est-à-dire des mots considérés comme valides dans les mots croisés et autres jeux de 16 | mots. Dans la collection Moby, le nom de fichier est 113809of.fic; vous pouvez télécharger une copie, 17 | avec le simple nom words.txt, de http://thinkpython2.com/code/words.txt. 18 | Ce fichier est en texte brut, vous pouvez donc l'ouvrir avec un éditeur de texte, mais vous pouvez également le lire à partir de 19 | Python. La fonction intégrée open prend le nom du fichier comme paramètre et retourne un 20 | objet fichier que vous pouvez utiliser pour lire le fichier. 21 | 22 | >>> fin = open('words.txt') 23 | fin est un nom commun pour un objet fichier utilisé pour la saisie. L'objet de fichier fournit plusieurs 24 | méthodes pour lire, y compris readline, qui lit les caractères du fichier jusqu'à ce qu'il soit 25 | à une nouvelle ligne et renvoie le résultat sous forme de chaîne: 26 | >>> fin.readline() 27 | 'aa\r\n' 28 | Le premier mot de cette liste est "aa", qui est une sorte de lave. La séquence \ r \ n 29 | représente deux caractères d'espacement, un retour chariot et une nouvelle ligne, qui séparent cette 30 | mot du suivant. 31 | L’objet fichier garde une trace de son emplacement dans le fichier, donc si vous appelez à nouveau readline, vous obtenez 32 | le mot suivant: 33 | 34 | 84 35 | 36 | Chapitre 9. Etude de cas: jeux de mots 37 | 38 | >>> fin.readline() 39 | 'aah\r\n' 40 | Le mot suivant est "aah", qui est un mot parfaitement légitime, alors arrête de me regarder comme 41 | ça. Ou, si c'est le blanc qui vous dérange, on peut s'en débarrasser avec un string 42 | bande de méthode: 43 | >>> line = fin.readline() 44 | >>> word = line.strip() 45 | >>> word 46 | 'aahed' 47 | Vous pouvez également utiliser un objet fichier dans le cadre d'une boucle for. Ce programme lit words.txt et 48 | imprime chaque mot, un par ligne: 49 | fin = open('words.txt') 50 | for line in fin: 51 | word = line.strip() 52 | print(word) 53 | 54 | 9.2 55 | 56 | Des exercices 57 | 58 | Il y a des solutions à ces exercices dans la section suivante. Vous devriez au moins essayer chacun 59 | un avant de lire les solutions. 60 | Exercice 9.1. Ecrire un programme qui lit des mots.txt et imprime seulement les mots avec plus de 20 61 | caractères (sans compter les espaces). 62 | Exercice 9.2. En 1939, Ernest Vincent Wright a publié un roman de 50 000 mots intitulé Gadsby 63 | ne contient pas la lettre "e". Puisque "e" est la lettre la plus courante en anglais, ce n'est pas facile de 64 | faire. 65 | En fait, il est difficile de construire une pensée solitaire sans utiliser ce symbole le plus commun. C'est 66 | ralentir au début, mais avec prudence et des heures d'entraînement, vous pouvez progressivement gagner de la facilité. 67 | D'accord, je vais m'arrêter maintenant. 68 | Ecrivez une fonction appelée has_no_e qui renvoie True si le mot donné n'a pas la lettre "e" dans 69 | il. 70 | Modifiez votre programme à partir de la section précédente pour n'imprimer que les mots sans "e" et calculez le pourcentage des mots de la liste sans "e". 71 | Exercice 9.3. Ecrire une fonction nommée évite qui prend un mot et une chaîne de lettres interdites, 72 | et qui renvoie True si le mot n'utilise aucune des lettres interdites. 73 | Modifiez votre programme pour inviter l'utilisateur à entrer une chaîne de lettres interdites, puis imprimez le 74 | nombre de mots qui n'en contiennent aucun. Pouvez-vous trouver une combinaison de 5 lettres interdites 75 | cela exclut le plus petit nombre de mots? 76 | Exercice 9.4. Écrivez une fonction nommée uses_only qui prend un mot et une chaîne de lettres, et 77 | qui renvoie True si le mot ne contient que des lettres dans la liste. Pouvez-vous faire une phrase en utilisant seulement 78 | les lettres acefhlo? Autre que "Hoe alfalfa?" 79 | Exercice 9.5. Écrivez une fonction nommée uses_all qui prend un mot et une chaîne de lettres requises, 80 | et qui renvoie True si le mot utilise toutes les lettres requises au moins une fois. Combien de mots sont 81 | là qui utilisent toutes les voyelles aeiou? Pourquoi pas aeiouy? 82 | Exercice 9.6. Ecrire une fonction appelée is_abecedarian qui renvoie True si les lettres d'un mot 83 | apparaissent dans l'ordre alphabétique (les lettres doubles sont correctes). Combien de mots abecedarian y a-t-il? 84 | 85 | 9.3. Chercher 86 | 87 | 9.3 88 | 89 | 85 90 | 91 | Chercher 92 | 93 | Tous les exercices de la section précédente ont quelque chose en commun. ils peuvent être résolus 94 | avec le modèle de recherche que nous avons vu dans la section 8.6. L'exemple le plus simple est: 95 | 96 | def has_no_e(word): 97 | for letter in word: 98 | if letter == 'e': 99 | return False 100 | return True 101 | La boucle for traverse les caractères du mot. Si nous trouvons la lettre "e", nous pouvons immédiatement 102 | retourner faux; sinon nous devons passer à la lettre suivante. Si nous quittons la boucle normalement, cela 103 | signifie que nous n'avons pas trouvé de "e", donc nous retournons True. 104 | Vous pourriez écrire cette fonction de manière plus concise en utilisant l'opérateur in, mais j'ai commencé avec cette 105 | version car elle démontre la logique du modèle de recherche. 106 | 107 | Avoids est une version plus générale de has_no_e mais elle a la même structure: 108 | def avoids(word, forbidden): 109 | for letter in word: 110 | if letter in forbidden: 111 | return False 112 | return True 113 | Nous pouvons retourner Faux dès que nous trouvons une lettre interdite; si nous arrivons à la fin de la boucle, 114 | nous retournons True. 115 | uses_only est similaire sauf que le sens de la condition est inversé: 116 | ef uses_only(word, available): 117 | for letter in word: 118 | if letter not in available: 119 | return False 120 | return True 121 | Au lieu d'une liste de lettres interdites, nous avons une liste de lettres disponibles. Si nous trouvons une lettre dans 122 | mot qui n'est pas disponible, nous pouvons retourner Faux. 123 | uses_all est similaire sauf que nous inversons le rôle du mot et de la chaîne de lettres: 124 | def uses_all (mot, requis): 125 | pour lettre en requis: 126 | si lettre pas en mot: 127 | retourner faux 128 | retourne True 129 | Au lieu de parcourir les lettres du mot, la boucle parcourt les lettres requises. Si l'un des 130 | les lettres requises n'apparaissent pas dans le mot, nous pouvons retourner Faux. 131 | Si vous pensiez vraiment comme un informaticien, vous auriez reconnu que 132 | uses_all était une instance d'un problème déjà résolu, et vous auriez écrit: 133 | 134 | def uses_all(word, required): 135 | return uses_only(required, word) 136 | Ceci est un exemple de plan de développement de programme appelé réduction à un problème déjà résolu 137 | problème, ce qui signifie que vous reconnaissez le problème sur lequel vous travaillez en tant qu'instance 138 | d'un problème résolu et appliquer une solution existante. 139 | 140 | 86 141 | 142 | 9.4 143 | 144 | Chapitre 9. Etude de cas: jeux de mots 145 | 146 | Boucler avec des indices 147 | 148 | J'ai écrit les fonctions dans la section précédente avec pour les boucles parce que je n'avais besoin que de la 149 | personnages dans les cordes; Je n'ai rien eu à faire avec les indices. 150 | Pour is_abecedarian nous devons comparer les lettres adjacentes, ce qui est un peu difficile avec un for 151 | boucle: 152 | 153 | def is_abecedarian(word): 154 | previous = word[0] 155 | for c in word: 156 | if c < previous: 157 | return False 158 | previous = c 159 | return True 160 | Une alternative consiste à utiliser la récursivité: 161 | 162 | def is_abecedarian(word): 163 | if len(word) <= 1: 164 | return True 165 | if word[0] > word[1]: 166 | return False 167 | return is_abecedarian(word[1:]) 168 | Une autre option consiste à utiliser une boucle while: 169 | 170 | def is_abecedarian(word): 171 | i = 0 172 | while i < len(word)-1: 173 | if word[i+1] < word[i]: 174 | return False 175 | i = i+1 176 | return True 177 | La boucle commence à i = 0 et se termine lorsque i = len (mot) -1. A chaque fois dans la boucle, il compare le caractère i (que vous pouvez considérer comme le personnage actuel) au i + 1 178 | personnage (que vous pouvez penser comme le suivant). 179 | Si le caractère suivant est inférieur à (alphabétiquement avant) le caractère actuel, alors nous avons découvert une rupture dans la tendance abécédaire, et nous renvoyons Faux. 180 | Si nous arrivons à la fin de la boucle sans trouver de défaut, le mot passe le test. À 181 | convainquez-vous que la boucle se termine correctement, considérez un exemple comme «flossy». le 182 | la longueur du mot est 6, donc la dernière fois que la boucle s'exécute est quand je est 4, qui est l'index de 183 | le dernier caractère. Lors de la dernière itération, il compare le dernier caractère 184 | au dernier, qui est ce que nous voulons. 185 | Voici une version de is_palindrome (voir exercice 6.3) qui utilise deux index; on commence à 186 | le début et monte; l'autre commence à la fin et descend. 187 | 188 | def is_palindrome(word): 189 | i = 0 190 | j = len(word)-1 191 | while i>> t = 'a', 'b', 'c', 'd', 'e' 19 | Bien que cela ne soit pas nécessaire, il est courant de placer les tuples entre parenthèses: 20 | >>> t = ('a', 'b', 'c', 'd', 'e') 21 | Pour créer un tuple avec un seul élément, vous devez inclure une dernière virgule: 22 | >>> t1 = 'a', 23 | >>> type (t1) 24 | 25 | Une valeur entre parenthèses n'est pas un tuple: 26 | >>> t2 = ('a') 27 | >>> type (t2) 28 | 29 | Un autre moyen de créer un tuple est le tuple à fonction intégrée. Sans argument, cela crée 30 | un tuple vide: 31 | >>> t = tuple () 32 | >>> t 33 | () 34 | 35 | 116 36 | 37 | Chapitre 12. Tuples 38 | 39 | Si l’argument est une séquence (chaîne, liste ou tuple), le résultat est un tuple avec les éléments de 40 | la séquence: 41 | 42 | >>> t = tuple('lupins') 43 | >>> t 44 | ('l', 'u', 'p', 'i', 'n', 's') 45 | Comme tuple est le nom d’une fonction intégrée, vous devriez éviter de l’utiliser comme nom de 46 | variable. 47 | La plupart des opérateurs de liste travaillent également sur des tuples. L'opérateur crochet indexe un élément: 48 | 49 | >>> t = ('a', 'b', 'c', 'd', 'e') 50 | >>> t [0] 51 | 'une' 52 | Et l'opérateur de tranche sélectionne une plage d'éléments. 53 | 54 | >>> t [1: 3] 55 | ('avant JC') 56 | Mais si vous essayez de modifier l'un des éléments du tuple, vous obtenez une erreur: 57 | 58 | >>> t [0] = 'A' 59 | TypeError: object doesn't support item assignment 60 | Les tuples étant immuables, vous ne pouvez pas modifier les éléments. Mais vous pouvez en remplacer un 61 | tuple avec un autre: 62 | 63 | >>> t = ('A',) + t [1:] 64 | >>> t 65 | ('A', 'b', 'c', 'd', 'e') 66 | Cette déclaration crée un nouveau tuple et y fait ensuite référence. 67 | Les opérateurs relationnels travaillent avec des tuples et d’autres séquences; Python commence par comparer 68 | le premier élément de chaque séquence. S'ils sont égaux, cela passe aux éléments suivants, et 69 | ainsi de suite, jusqu'à ce qu'il trouve des éléments différents. Les éléments suivants ne sont pas pris en compte (même si 70 | ils sont vraiment gros). 71 | 72 | >>> (0, 1, 2) <(0, 3, 4) 73 | Vrai 74 | >>> (0, 1, 2000000) <(0, 3, 4) 75 | Vrai 76 | 77 | 12.2 78 | 79 | Affectation de tuple 80 | 81 | Il est souvent utile d’échanger les valeurs de deux variables. Avec l'usage conventionnel, vous 82 | devez utiliser une variable temporaire. Par exemple, pour échanger a et b: 83 | 84 | >>> temp = a 85 | >>> a = b 86 | >>> b = temp 87 | Cette solution est lourde; L’affectation du tuple est plus élégante: 88 | 89 | >>> a, b = b, a 90 | 91 | 12.3 Tuples comme valeurs de retour 92 | 93 | 117 94 | 95 | Le côté gauche est un tuple de variables; le côté droit est un tuple d'expressions. Chaque valeur 96 | est affecté à sa variable respective. Toutes les expressions du côté droit sont évaluées 97 | avant l'une des affectations. 98 | Le nombre de variables à gauche et le nombre de valeurs à droite doivent être les mêmes. 99 | même: 100 | 101 | >>> a, b = 1, 2, 3 102 | ValueError: too many values to unpack 103 | Plus généralement, le côté droit peut être n’importe quel type de séquence (chaîne, liste ou tuple). Par exemple, pour fractionner une adresse électronique en un nom d'utilisateur et un domaine, vous pouvez écrire: 104 | 105 | >>> addr = 'monty@python.org' 106 | >>> uname, domain = addr.split ('@') 107 | La valeur renvoyée par split est une liste avec deux éléments. le premier élément est affecté à 108 | uname, le second au domaine. 109 | 110 | >>> uname 111 | 'monty' 112 | >>> domaine 113 | 'python.org' 114 | 115 | 12.3 116 | 117 | Tuples comme valeurs de retour 118 | 119 | Strictement parlant, une fonction ne peut renvoyer qu’une seule valeur, mais si la valeur est un tuple, l’effet 120 | équivaut à renvoyer plusieurs valeurs. Par exemple, si vous voulez diviser deux entiers 121 | et calculer le quotient et le reste, il est inefficace de calculer x / y puis x% y. Il 122 | est préférable de les calculer tous les deux en même temps. 123 | La fonction intégrée divmod prend deux arguments et retourne un tuple de deux valeurs, le 124 | quotient et reste. Vous pouvez stocker le résultat sous forme de tuple: 125 | 126 | >>> t = divmod (7, 3) 127 | >>> t 128 | (2, 1) 129 | Ou utilisez l’assignation de tuple pour stocker les éléments séparément: 130 | 131 | >>> quot, rem = divmod (7, 3) 132 | >>> quot 133 | 2 134 | >>> rem 135 | 1 136 | Voici un exemple de fonction qui retourne un tuple: 137 | 138 | def min_max (t): 139 | retour min (t), max (t) 140 | max et min sont des fonctions intégrées qui recherchent les éléments les plus grands et les plus petits d'une séquence. 141 | min_max calcule les deux et retourne un tuple de deux valeurs. 142 | 143 | 118 144 | 145 | 12.4 146 | 147 | Chapitre 12. Tuples 148 | 149 | Tuples d'argument de longueur variable 150 | 151 | Les fonctions peuvent prendre un nombre variable d'arguments. Un nom de paramètre qui commence par 152 | * rassemble des arguments dans un tuple. Par exemple, printall prend n'importe quel nombre d'arguments 153 | et les imprime: 154 | 155 | def printall (* args): 156 | print (args) 157 | Le paramètre rassembler peut avoir n'importe quel nom, mais args est conventionnel. Voici comment 158 | la fonction fonctionne: 159 | 160 | >>> printall (1, 2.0, '3') 161 | (1, 2.0, '3') 162 | Le complément de collecte est dispersé. Si vous avez une séquence de valeurs et que vous voulez passer 163 | Pour une fonction sous forme d'arguments multiples, vous pouvez utiliser l'opérateur *. Par exemple, divmod 164 | prend exactement deux arguments; ça ne marche pas avec un tuple: 165 | 166 | >>> t = (7, 3) 167 | >>> divmod (t) 168 | TypeError: divmod expected 2 arguments, got 1 169 | Mais si vous dispersez le tuple, cela fonctionne: 170 | 171 | >>> divmod (* t) 172 | (2, 1) 173 | La plupart des fonctions intégrées utilisent des tuples d'arguments de longueur variable. Par exemple, max et 174 | min peut prendre n'importe quel nombre d'arguments: 175 | 176 | >>> max (1, 2, 3) 177 | 3 178 | Mais la somme ne le fait pas. 179 | 180 | >>> sum(1, 2, 3) 181 | TypeError: sum expected at most 2 arguments, got 3 182 | En tant qu’exercice, écrivez une fonction appelée sumall qui prend un nombre quelconque d’arguments et 183 | retourne leur somme. 184 | 185 | 12.5 186 | 187 | Listes et tuples 188 | 189 | zip est une fonction intégrée qui prend deux séquences ou plus et renvoie une liste de tuples où 190 | chaque tuple contient un élément de chaque séquence. Le nom de la fonction fait référence à un 191 | fermeture à glissière, qui relie et entrelace deux rangées de dents. 192 | Cet exemple extrait une chaîne et une liste: 193 | 194 | >>> s = 'abc' 195 | >>> t = [0, 1, 2] 196 | >>> zip (s, t) 197 | 198 | Le résultat est un objet zip qui sait comment parcourir les paires. Le plus commun 199 | l'utilisation de zip est dans une boucle for: 200 | 201 | 12.5 Listes et tuples 202 | 203 | 119 204 | 205 | >>> for pair in zip(s, t): 206 | ... 207 | print (paire) 208 | ... 209 | ('a', 0) 210 | ('b', 1) 211 | ('c', 2) 212 | Un objet zip est une sorte d'itérateur, c'est-à-dire tout objet qui itère dans une séquence. 213 | Les itérateurs ressemblent aux listes à certains égards, mais contrairement aux listes, vous ne pouvez pas utiliser un index pour sélectionner 214 | un élément d'un itérateur. 215 | Si vous souhaitez utiliser des opérateurs et des méthodes de liste, vous pouvez utiliser un objet zip pour créer une liste: 216 | 217 | >>> liste (zip (s, t)) 218 | [('a', 0), ('b', 1), ('c', 2)] 219 | Le résultat est une liste de tuples; dans cet exemple, chaque tuple contient un caractère de la chaîne 220 | et l'élément correspondant de la liste. 221 | Si les séquences ne sont pas de la même longueur, le résultat a la longueur de la plus courte. 222 | 223 | >>> liste (zip ('Anne', 'Elk')) 224 | [('A', 'E'), ('n', 'l'), ('n', 'k')] 225 | Vous pouvez utiliser l’affectation de tuples dans une boucle for pour parcourir une liste de tuples: 226 | t = [('a', 0), ('b', 1), ('c', 2)] 227 | for letter, number in t: 228 | print(number, letter 229 | À chaque passage dans la boucle, Python sélectionne le tuple suivant dans la liste et attribue les éléments à une lettre et à un chiffre. La sortie de cette boucle est: 230 | 0 a 231 | 1 b 232 | 2 c 233 | Si vous combinez les affectations zip, for et tuple, vous obtenez un idiome utile pour parcourir deux 234 | (ou plus) séquences en même temps. Par exemple, has_match prend deux séquences, t1 235 | et t2, et renvoie True s'il existe un indice i tel que t1 [i] == t2 [i]: 236 | def has_match(t1, t2): 237 | for x, y in zip(t1, t2): 238 | if x == y: 239 | return True 240 | return False 241 | Si vous devez parcourir les éléments d’une séquence et leurs index, vous pouvez utiliser la fonction intégrée. 242 | fonction énumérer: 243 | pour index, élément dans énumération ('abc'): 244 | print (index, element) 245 | Le résultat de énumération est un objet énuméré, qui itère une séquence de paires; chaque 246 | La paire contient un index (à partir de 0) et un élément de la séquence donnée. Dans ce 247 | Par exemple, la sortie est 248 | 0 a 249 | 1 b 250 | 2 c 251 | Encore. 252 | 253 | 120 254 | 255 | 12.6 256 | 257 | Chapitre 12. Tuples 258 | 259 | Dictionnaires et tuples 260 | 261 | Les dictionnaires ont une méthode appelée items qui retourne une séquence de tuples, où chaque 262 | tuple est une paire clé-valeur. 263 | 264 | >>> d = {'a': 0, 'b': 1, 'c': 2} 265 | >>> t = d.items () 266 | >>> t 267 | dict_items ([('c', 2), ('a', 0), ('b', 1)]) 268 | Le résultat est un objet dict_items, qui est un itérateur qui itère les paires clé-valeur. Vous 269 | peut l'utiliser dans une boucle comme celle-ci: 270 | >>> for key, value in d.items(): 271 | ... 272 | print(key, value) 273 | ... 274 | c 2 275 | un 0 276 | b 1 277 | Comme vous pouvez vous attendre d'un dictionnaire, les éléments ne sont dans aucun ordre particulier. 278 | En allant dans l'autre sens, vous pouvez utiliser une liste de tuples pour initialiser un nouveau dictionnaire: 279 | 280 | >>> t = [('a', 0), ('c', 2), ('b', 1)] 281 | >>> d = dict (t) 282 | >>> d 283 | {'a': 0, 'c': 2, 'b': 1} 284 | En combinant dict et zip, vous créez un dictionnaire de manière concise: 285 | >>> d = dict (zip ('abc', range (3))) 286 | >>> d 287 | {'a': 0, 'c': 2, 'b': 1} 288 | La mise à jour de la méthode du dictionnaire prend également une liste de tuples et les ajoute, sous forme de paires clé-valeur, 289 | vers un dictionnaire existant. 290 | Il est courant d’utiliser des tuples comme clés dans les dictionnaires (principalement parce que vous ne pouvez pas utiliser de listes). Pour 291 | Par exemple, un annuaire téléphonique peut mapper des paires nom-prénom-prénom sur téléphone 292 | Nombres. En supposant que nous ayons défini dernier, premier et nombre, nous pourrions écrire: 293 | 294 | répertoire [dernier, premier] = numéro 295 | L'expression entre parenthèses est un tuple. Nous pourrions utiliser l’assignation de tuples pour parcourir ce dictionnaire. 296 | pour la première fois dans le répertoire: 297 | print (premier, dernier, répertoire [dernier, premier]) 298 | Cette boucle traverse les clés du répertoire, qui sont des tuples. Il assigne les éléments de chaque 299 | tuple to last et first, puis imprime le nom et le numéro de téléphone correspondant. 300 | Il existe deux manières de représenter des tuples dans un diagramme d'état. La version plus détaillée 301 | affiche les index et les éléments tels qu’ils apparaissent dans une liste. Par exemple, le tuple 302 | ('Cleese', 'John') apparaîtrait comme dans la figure 12.1. 303 | Mais dans un diagramme plus grand, vous voudrez peut-être omettre les détails. Par exemple, un diagramme de 304 | l'annuaire téléphonique peut apparaître comme à la figure 12.2. 305 | Ici, les tuples sont montrés en utilisant la syntaxe Python comme un raccourci graphique. Le téléphone 306 | Le numéro dans le diagramme correspond à la ligne de réclamation de la BBC. Ne l'appelez donc pas. 307 | 308 | 12.7. Séquences de séquences 309 | 310 | 121 311 | tuple 312 | 0 313 | 314 | «Cleese» 315 | 316 | 1 317 | 318 | 'John' 319 | 320 | Figure 12.1: Diagramme d'état. 321 | dict 322 | («Cleese», «John») 323 | 324 | «08700 100 222» 325 | 326 | («Chapman», «Graham») 327 | 328 | «08700 100 222» 329 | 330 | ("Idle", "Eric") 331 | 332 | «08700 100 222» 333 | 334 | («Gilliam», «Terry») 335 | 336 | «08700 100 222» 337 | 338 | ("Jones", "Terry") 339 | 340 | «08700 100 222» 341 | 342 | («Palin», «Michael») 343 | 344 | «08700 100 222» 345 | 346 | Figure 12.2: Diagramme d'état. 347 | 348 | 12.7 349 | 350 | Séquences de séquences 351 | 352 | Je me suis concentré sur les listes de tuples, mais presque tous les exemples de ce chapitre fonctionnent également. 353 | avec des listes de listes, des tuples de tuples et des tuples de listes. Pour éviter d’énumérer les possibles 354 | combinaisons, il est parfois plus facile de parler de séquences de séquences. 355 | Dans de nombreux contextes, les différents types de séquences (chaînes, listes et tuples) peuvent être utilisés 356 | de façon interchangeable. Alors, comment devriez-vous choisir un sur les autres? 357 | Pour commencer, les chaînes sont plus limitées que les autres séquences car les éléments doivent être des caractères. Ils sont également immuables. Si vous avez besoin de pouvoir changer le 358 | caractères dans une chaîne (par opposition à la création d’une nouvelle chaîne), vous pouvez utiliser une liste de 359 | caractères à la place. 360 | Les listes sont plus courantes que les tuples, principalement parce qu'elles sont mutables. Mais il y a quelques 361 | cas où vous pourriez préférer des tuples: 362 | 1. Dans certains contextes, comme une instruction return, il est syntaxiquement plus simple de créer un tuple. 363 | qu'une liste. 364 | 2. Si vous souhaitez utiliser une séquence comme clé de dictionnaire, vous devez utiliser un type immuable. 365 | comme un tuple ou une ficelle. 366 | 3. Si vous passez une séquence en tant qu’argument à une fonction, l’utilisation de tuples réduit le 367 | potentiel de comportement inattendu en raison de crénelage. 368 | Les tuples étant immuables, ils ne fournissent pas de méthodes telles que trier et inverser, 369 | modifier les listes existantes. Mais Python fournit la fonction intégrée triée, qui prend n'importe quelle 370 | séquence et retourne une nouvelle liste avec les mêmes éléments dans l’ordre trié et inversé, 371 | qui prend une séquence et retourne un itérateur qui parcourt la liste dans l’ordre inverse. 372 | 373 | 122 374 | 375 | 12.8 376 | 377 | Chapitre 12. Tuples 378 | 379 | Débogage 380 | 381 | Les listes, les dictionnaires et les tuples sont des exemples de structures de données. dans ce chapitre, nous commençons 382 | pour voir les structures de données composées, comme des listes de tuples, ou des dictionnaires contenant des tuples 383 | clés et listes en tant que valeurs. Les structures de données composées sont utiles, mais elles sont sujettes à ce que 384 | J'appelle des erreurs de forme; c’est-à-dire les erreurs causées par le type, la taille ou la taille incorrecte d’une structure de données. 385 | Par exemple, si vous attendez une liste avec un entier et que je vous donne un simple 386 | entier (pas dans une liste), ça ne marchera pas. 387 | Pour aider à déboguer ce genre d’erreurs, j’ai écrit un module appelé structshape qui 388 | fournit une fonction, également appelée structshape, qui prend tout type de structure de données 389 | un argument et retourne une chaîne qui résume sa forme. Vous pouvez le télécharger à partir de 390 | http://thinkpython2.com/code/structshape.py 391 | Voici le résultat pour une liste simple: 392 | 393 | >>> depuis structshape import structshape 394 | >>> t = [1, 2, 3] 395 | >>> structshape (t) 396 | 'liste de 3 int' 397 | Un programme plus sophistiqué pourrait écrire «liste de 3 ints», mais il était plus facile de ne pas traiter les pluriels. 398 | Voici une liste de listes: 399 | 400 | >>> t2 = [[1,2], [3,4], [5,6]] 401 | >>> structshape (t2) 402 | 'liste de 3 liste de 2 int' 403 | Si les éléments de la liste ne sont pas du même type, structshape les regroupe, dans l’ordre, en 404 | type: 405 | 406 | >>> t3 = [1, 2, 3, 4.0, '5', '6', [7], [8], 9] 407 | >>> structshape (t3) 408 | 'liste de (3 int, float, 2 str, 2 liste de int, int)' 409 | Voici une liste de tuples: 410 | 411 | >>> s = 'abc' 412 | >>> lt = list (zip (t, s)) 413 | >>> structshape (lt) 414 | 'liste de 3 tuple de (int, str)' 415 | Et voici un dictionnaire avec 3 éléments qui mappent des entiers à des chaînes. 416 | 417 | >>> d = dict (lt) 418 | >>> structshape (d) 419 | 'dict of 3 int-> str' 420 | Si vous ne parvenez pas à suivre vos structures de données, structshape peut vous aider. 421 | 422 | 12.9 423 | 424 | Glossaire 425 | 426 | tuple: séquence immuable d'éléments. 427 | Attribution de tuple: Une affectation avec une séquence à droite et un tuple de variables à gauche. Le côté droit est évalué, puis ses éléments sont affectés au 428 | variables à gauche. 429 | 430 | 12.10. Des exercices 431 | 432 | 123 433 | 434 | recueillir: l'opération d'assemblage d'un tuple d'argument de longueur variable. 435 | scatter: opération consistant à traiter une séquence comme une liste d'arguments. 436 | objet zip: résultat de l'appel d'une fonction intégrée zip; un objet qui itère à travers un 437 | séquence de tuples. 438 | itérateur: objet pouvant parcourir une séquence, mais ne fournissant pas de liste 439 | opérateurs et méthodes. 440 | structure de données: ensemble de valeurs associées, souvent organisées en listes, dictionnaires, tuples, 441 | etc. 442 | shape error: erreur due à la forme incorrecte d'une valeur; c'est le mauvais type 443 | ou la taille. 444 | 445 | 12.10 446 | 447 | Des exercices 448 | 449 | Exercice 12.1. Ecrivez une fonction appelée most_frequent qui prend une chaîne et affiche les lettres par ordre décroissant de fréquence. Trouvez des échantillons de texte de plusieurs langues et voyez 450 | comment la fréquence des lettres varie d'une langue à l'autre. Comparez vos résultats avec les tableaux sur http: 451 | // en. Wikipédia. fréquences org / wiki / Letter_. Solution: http: // thinkpython2. 452 | com / code / le plus fréquent. py. 453 | Exercice 12.2. Plus d'anagrammes! 454 | 1. Ecrivez un programme qui lit une liste de mots d’un fichier (voir Section 9.1) et imprime tous les ensembles de 455 | mots qui sont des anagrammes. 456 | Voici un exemple de ce à quoi la sortie pourrait ressembler: 457 | 458 | ['deltas', 'desal', 'durés', 'salés', 'slated', 'staled'] 459 | ['conserves', 'ternaires'] 460 | ['générer', 'grandir'] 461 | ['resmelts', 'fondeurs', 'termless'] 462 | Astuce: vous voudrez peut-être créer un dictionnaire qui mappe une collection de lettres sur une liste 463 | des mots qui peuvent être orthographiés avec ces lettres. La question est, comment pouvez-vous représenter le 464 | collection de lettres d’une manière qui puisse être utilisée comme clé? 465 | 2. Modifiez le programme précédent de sorte qu'il imprime d'abord la liste la plus longue d'anagrammes, suivie de 466 | le deuxième plus long, et ainsi de suite. 467 | 3. Au Scrabble, un «bingo» consiste à jouer les sept tuiles de votre rack, avec une lettre sur 468 | le conseil, pour former un mot de huit lettres. Quelle collection de 8 lettres forme le plus possible 469 | des bingos? Indice: il y en a sept. 470 | Solution: http: // thinkpython2. com / code / anagram_ ensembles. py. 471 | Exercice 12.3. Deux mots forment un «couple de métathèse» si vous pouvez transformer l’un en l’autre en 472 | échanger deux lettres; par exemple, «converser» et «conserver». Ecrivez un programme qui trouve tous 473 | les paires de métathèse dans le dictionnaire. Astuce: ne testez pas toutes les paires de mots, et ne testez pas tous les mots possibles 474 | échanges. Solution: http: // thinkpython2. com / code / métathèse. py. Crédit: Cet exercice 475 | est inspiré par un exemple sur http: // puzzlers. org. 476 | 477 | 124 478 | 479 | Chapitre 12. Tuples 480 | 481 | Exercice 12.4. Voici un autre Car Talk Puzzler (http: // www. Cartalk. Com / content / 482 | casse-tête): 483 | Quel est le mot anglais le plus long, qui reste un mot anglais valide, car vous enlevez son 484 | lettres une à la fois? 485 | Désormais, les lettres peuvent être supprimées à l’une des extrémités ou au milieu, mais vous ne pouvez pas réorganiser les lettres. 486 | des lettres. Chaque fois que vous laissez tomber une lettre, vous vous retrouvez avec un autre mot anglais. Si 487 | vous faites cela, vous allez finir par vous retrouver avec une lettre et ça aussi va 488 | être un mot anglais - celui qui est trouvé dans le dictionnaire. Je veux savoir quel est le 489 | Le mot le plus long et combien de lettres a-t-il? 490 | Je vais vous donner un petit exemple modeste: Sprite. D'accord? Vous commencez avec sprite, 491 | vous enlevez une lettre, une de l’intérieur du mot, vous enlevez le r, et on nous laisse 492 | avec le mot dépit, puis on enlève le e de la fin, on nous laisse à la broche, on enlève le s, 493 | nous sommes partis avec pit, lui et moi 494 | Ecrivez un programme pour trouver tous les mots pouvant être réduits de cette façon, puis trouvez le plus long. 495 | Cet exercice est un peu plus difficile que la plupart des autres, alors voici quelques suggestions: 496 | 1. Vous voudrez peut-être écrire une fonction qui prend un mot et calcule une liste de tous les mots qui 497 | peut être formé en enlevant une lettre. Ce sont les "enfants" de la parole. 498 | 2. Récursivement, un mot est réductible si l'un de ses enfants est réductible. Comme base, vous pouvez 499 | considérez la chaîne vide réductible. 500 | 3. La liste de mots que j'ai fournie, words.txt, ne contient pas de mots composés d'une seule lettre. Donc vous voudrez peut-être 501 | pour ajouter “I”, “a” et la chaîne vide. 502 | 4. Pour améliorer les performances de votre programme, vous voudrez peut-être mémoriser les mots qui sont 503 | connu pour être réductible. 504 | Solution: http: // thinkpython2. com / code / réductible. py. -------------------------------------------------------------------------------- /ch15Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 15 2 | 3 | Classes et objets 4 | À ce stade, vous devez savoir utiliser des fonctions pour organiser le code et des types intégrés pour organiser 5 | les données. L'étape suivante consiste à apprendre la «programmation orientée objet», qui utilise des types définis par le programmeur pour organiser le code et les données. La programmation orientée objet est un sujet important. 6 | il faudra quelques chapitres pour y arriver. 7 | Des exemples de code de ce chapitre sont disponibles à l'adresse http://thinkpython2.com/code/. 8 | Point1.py; les solutions aux exercices sont disponibles sur http://thinkpython2.com/code/ 9 | Point1_soln.py. 10 | 11 | 15.1 12 | 13 | Types définis par le programmeur 14 | 15 | Nous avons utilisé de nombreux types intégrés de Python; maintenant nous allons définir un nouveau type. Comme 16 | par exemple, nous allons créer un type appelé Point qui représente un point en deux dimensions 17 | espace. 18 | En notation mathématique, les points sont souvent écrits entre parenthèses avec une virgule séparant 19 | les coordonnées. Par exemple, (0, 0) représente l’origine et (x, y) représente le point x 20 | unités à droite et y unités à partir de l'origine. 21 | Il y a plusieurs façons de représenter des points en Python: 22 | • Nous pourrions stocker les coordonnées séparément dans deux variables, x et y. 23 | • Nous pourrions stocker les coordonnées sous forme d'éléments dans une liste ou un tuple. 24 | • Nous pourrions créer un nouveau type pour représenter les points sous forme d'objets. 25 | La création d’un nouveau type est plus compliquée que les autres options, mais elle présente les avantages suivants qui 26 | seront apparents bientôt. 27 | Un type défini par le programmeur est également appelé une classe. Une définition de classe ressemble à ceci: 28 | 29 | class Point: 30 | """Represents a point in 2-D space.""" 31 | 32 | 148 33 | 34 | Chapitre 15. Classes et objets 35 | Point 36 | blanc 37 | 38 | X 39 | 40 | 3.0 41 | 42 | y 43 | 44 | 4.0 45 | 46 | Figure 15.1: Diagramme d'objets. 47 | L'en-tête indique que la nouvelle classe s'appelle Point. Le corps est une docstring qui explique le rôle de la classe. Vous pouvez définir des variables et des méthodes dans une définition de classe, 48 | mais nous y reviendrons plus tard. 49 | La définition d'une classe nommée Point crée un objet de classe. 50 | 51 | >>> Point 52 | 53 | Comme Point est défini au niveau supérieur, son “nom complet” est __main __.Point. 54 | L'objet de classe est comme une fabrique pour créer des objets. Pour créer un point, vous appelez Point comme si 55 | c'était une fonction. 56 | 57 | >>> blank = Point() 58 | >>> blank 59 | <__main__.Point object at 0xb7e9d3ac> 60 | La valeur de retour est une référence à un objet Point, que nous affectons à vide. 61 | La création d'un nouvel objet s'appelle instanciation et l'objet est une instance de la classe. 62 | Lorsque vous imprimez une instance, Python vous indique à quelle classe elle appartient et où elle est stockée. 63 | en mémoire (le préfixe 0x signifie que le nombre suivant est en hexadécimal). 64 | Chaque objet est une instance d'une classe, donc «objet» et «instance» sont interchangeables. 65 | Mais dans ce chapitre, j'utilise «instance» pour indiquer que je parle d'un type défini par le programmeur. 66 | 67 | 15.2 68 | 69 | Les attributs 70 | 71 | Vous pouvez affecter des valeurs à une instance à l'aide de la notation par points: 72 | 73 | >>> blank.x = 3.0 74 | >>> blank.y = 4.0 75 | Cette syntaxe est similaire à celle utilisée pour sélectionner une variable dans un module, telle que math.pi. 76 | ou string.whitespace. Dans ce cas, cependant, nous assignons des valeurs aux éléments nommés de 77 | un objet. Ces éléments sont appelés attributs. 78 | En tant que nom, “AT-trib-ute” est prononcé en insistant sur la première syllabe, par opposition à 79 | “A-TRIB-ute”, qui est un verbe. 80 | Le diagramme suivant montre le résultat de ces affectations. Un diagramme d'état qui montre 81 | un objet et ses attributs s'appelle un diagramme d'objet; voir la figure 15.1. 82 | La variable blank fait référence à un objet Point, qui contient deux attributs. Chaque attribut 83 | fait référence à un nombre à virgule flottante. 84 | Vous pouvez lire la valeur d'un attribut en utilisant la même syntaxe: 85 | 86 | 15.3 Les rectangles 87 | 88 | 149 89 | 90 | >>> blank.y 91 | 4.0 92 | >>> x = blank.x 93 | >>> x 94 | 3.0 95 | L’expression blank.x signifie que «Aller à l’objet vide se réfère à et obtient la valeur de x». 96 | Dans l'exemple, nous attribuons cette valeur à une variable nommée x. Il n'y a pas de conflit entre le 97 | la variable x et l'attribut x. 98 | Vous pouvez utiliser la notation par points dans toute expression. Par exemple: 99 | 100 | >>> '(% g,% g)'% (blank.x, blank.y) 101 | '(3.0, 4.0)' 102 | >>> distance = math.sqrt (blank.x ** 2 + blank.y ** 2) 103 | >>> distance 104 | 5.0 105 | Vous pouvez passer une instance comme argument de la manière habituelle. Par exemple: 106 | 107 | def print_point (p): 108 | print ('(% g,% g)'% (p.x, p.y)) 109 | print_point prend un point comme argument et l'affiche en notation mathématique. Pour 110 | l'invoquez, vous pouvez passer blanc comme argument: 111 | >>> print_point(blank) 112 | (3.0, 4.0) 113 | Dans la fonction, p est un alias pour un blanc. Par conséquent, si la fonction modifie p, ce dernier change. 114 | En exercice, écrivez une fonction appelée distance_between_points qui prend deux points comme 115 | arguments et renvoie la distance entre eux. 116 | 117 | 15.3 118 | 119 | Les rectangles 120 | 121 | Parfois, il est évident que les attributs d’un objet devraient être, mais d’autres fois vous avez 122 | prendre des décisions. Par exemple, imaginez que vous concevez une classe pour représenter des rectangles. 123 | Quels attributs utiliseriez-vous pour spécifier l'emplacement et la taille d'un rectangle? Vous pouvez ignorer l'angle. pour que les choses restent simples, supposons que le rectangle soit vertical ou horizontal. 124 | Il y a au moins deux possibilités: 125 | • Vous pouvez spécifier un coin du rectangle (ou le centre), la largeur et le 126 | la taille. 127 | • Vous pouvez spécifier deux coins opposés. 128 | À ce stade, il est difficile de dire si l’un est meilleur que l’autre, nous allons donc mettre en œuvre le 129 | premier, juste à titre d'exemple. 130 | Voici la définition de la classe: 131 | 132 | 150 133 | 134 | Chapitre 15. Classes et objets 135 | Rectangle 136 | boîte 137 | 138 | largeur 139 | 140 | 100.0 141 | 142 | la taille 143 | 144 | 200.0 145 | 146 | coin 147 | 148 | Point 149 | X 150 | 151 | 0.0 152 | 153 | y 154 | 155 | 0.0 156 | 157 | Figure 15.2: Diagramme d'objets. 158 | 159 | class Rectangle: 160 | """Represents a rectangle. 161 | attributes: width, height, corner. 162 | """ 163 | La docstring répertorie les attributs: width et height sont des nombres; corner est un objet Point 164 | qui spécifie le coin inférieur gauche. 165 | Pour représenter un rectangle, vous devez instancier un objet Rectangle et attribuer des valeurs à la 166 | les attributs: 167 | 168 | box = Rectangle() 169 | box.width = 100.0 170 | box.height = 200.0 171 | box.corner = Point() 172 | box.corner.x = 0.0 173 | box.corner.y = 0.0 174 | L’expression box.corner.x signifie «Aller à l’objet dont la boîte se réfère à et sélectionnez l’attribut». 175 | nommé coin; puis allez à cet objet et sélectionnez l'attribut nommé x. ” 176 | La figure 15.2 montre l'état de cet objet. Un objet qui est un attribut d'un autre objet est 177 | intégré. 178 | 179 | 15.4 180 | 181 | Instances en tant que valeurs de retour 182 | 183 | Les fonctions peuvent renvoyer des instances. Par exemple, find_center prend un rectangle comme argument et retourne un point contenant les coordonnées du centre du rectangle: 184 | 185 | def find_center(rect): 186 | p = Point() 187 | p.x = rect.corner.x + rect.width/2 188 | p.y = rect.corner.y + rect.height/2 189 | return p 190 | Voici un exemple qui passe case en tant qu’argument et assigne le point résultant à 191 | centre: 192 | 193 | >>> center = find_center(box) 194 | >>> print_point(center) 195 | (50, 100) 196 | 197 | 15.5 Les objets sont mutables 198 | 199 | 15.5 200 | 201 | 151 202 | 203 | Les objets sont mutables 204 | 205 | Vous pouvez modifier l'état d'un objet en affectant l'un de ses attributs. Pour 206 | Par exemple, pour changer la taille d’un rectangle sans changer sa position, vous pouvez modifier 207 | les valeurs de largeur et de hauteur: 208 | 209 | box.width = box.width + 50 210 | box.height = box.height + 100 211 | Vous pouvez également écrire des fonctions qui modifient des objets. Par exemple, grow_rectangle prend une 212 | Objet rectangle et deux nombres, dwidth et dheight, et ajoute les nombres au 213 | largeur et hauteur du rectangle: 214 | 215 | def grow_rectangle(rect, dwidth, dheight): 216 | rect.width += dwidth 217 | rect.height += dheight 218 | Voici un exemple qui illustre l'effet: 219 | 220 | >>> box.width, box.height 221 | (150.0, 300.0) 222 | >>> grow_rectangle(box, 50, 100) 223 | >>> box.width, box.height 224 | (200.0, 400.0) 225 | Dans la fonction, rect est un alias pour box. Ainsi, lorsque la fonction modifie rect, box 226 | change. 227 | Comme exercice, écrivez une fonction nommée move_rectangle qui prend un rectangle et deux 228 | nombres nommés dx et dy. Il faut changer l’emplacement du rectangle en ajoutant dx à 229 | la coordonnée x du coin et l’ajout de dy à la coordonnée y du coin. 230 | 231 | 15.6 232 | 233 | Copier 234 | 235 | L'aliasing peut rendre un programme difficile à lire car des modifications dans un endroit peuvent avoir 236 | effets inattendus dans un autre endroit. Il est difficile de garder une trace de toutes les variables qui pourraient 237 | se référer à un objet donné. 238 | Copier un objet est souvent une alternative au repliement. Le module de copie contient une fonction appelée 239 | Copy qui peut dupliquer n'importe quel objet: 240 | 241 | >>> p1 = Point() 242 | >>> p1.x = 3.0 243 | >>> p1.y = 4.0 244 | >>> import copy 245 | >>> p2 = copy.copy(p1) 246 | p1 and p2 contain the same data, but they are not the same Point. 247 | >>> print_point(p1) 248 | (3, 4) 249 | >>> print_point(p2) 250 | (3, 4) 251 | >>> p1 is p2 252 | False 253 | 254 | 152 255 | 256 | Chapitre 15. Classes et objets 257 | boîte 258 | 259 | largeur 260 | 261 | 100.0 262 | 263 | 100.0 264 | 265 | largeur 266 | 267 | la taille 268 | 269 | 200.0 270 | 271 | 200.0 272 | 273 | la taille 274 | 275 | coin 276 | 277 | X 278 | 279 | 0.0 280 | 281 | y 282 | 283 | 0.0 284 | 285 | box2 286 | 287 | coin 288 | 289 | Figure 15.3: Diagramme d'objets. 290 | 291 | >>> p1 == p2 292 | Faux 293 | L'opérateur is indique que p1 et p2 ne sont pas le même objet, ce à quoi nous nous attendions. Mais vous auriez pu vous attendre == à produire True car ces points contiennent le 294 | mêmes données. Dans ce cas, vous serez déçu d'apprendre que, pour les instances, par défaut 295 | le comportement de l'opérateur == est identique à celui de l'opérateur is; il vérifie l'identité des l'objet, pas 296 | équivalence d'objet. C’est parce que, pour les types définis par le programmeur, Python ne sait pas 297 | ce qui devrait être considéré comme équivalent. Au moins pas encore. 298 | Si vous utilisez copy.copy pour dupliquer un rectangle, vous constaterez qu'il copie l'objet 299 | rectangle mais pas le point incorporé. 300 | 301 | >>> box2 = copy.copy(box) 302 | >>> box2 is box 303 | False 304 | >>> box2.corner is box.corner 305 | True 306 | Le dessin 15.3 montre l'aspect du diagramme d'objets. Cette opération s'appelle shallow 307 | copy car il copie l'objet et toutes les références qu'il contient, mais pas l'objet 308 | incorporé. 309 | Pour la plupart des applications, ce n’est pas ce que vous voulez. 310 | Dans cet exemple, invoquer 311 | grow_rectangle sur l’un des rectangles n’affecterait pas l’autre, mais invoquerait 312 | move_rectangle sur l'un ou l'autre affecterait les deux! Ce comportement est source de confusion et d’erreurs. 313 | Heureusement, le module de copie fournit une méthode appelée deepcopy qui copie non seulement 314 | l'objet, mais aussi les objets auxquels il fait référence, et les objets auxquels ils font référence, et ainsi de suite. Tu ne vas pas 315 | soyez surpris d'apprendre que cette opération s'appelle une copie profonde (deep copy). 316 | 317 | >>> box3 = copy.deepcopy(box) 318 | >>> box3 is box 319 | False 320 | >>> box3.corner is box.corner 321 | False 322 | box3 et box sont des objets complètement séparés. 323 | Comme exercice, écrivez une version de move_rectangle qui crée et retourne un nouveau rectangle 324 | au lieu de modifier l'ancien. 325 | 326 | 15.7 327 | 328 | Débogage 329 | 330 | Lorsque vous commencez à utiliser des objets, vous risquez de rencontrer de nouvelles exceptions. Si 331 | vous essayez d’accéder à un attribut qui n’existe pas, vous obtenez un AttributeError: 332 | 333 | 15.8. Glossaire 334 | 335 | 153 336 | 337 | >>> p = Point() 338 | >>> p.x = 3 339 | >>> p.y = 4 340 | >>> p.z 341 | AttributeError: Point instance has no attribute 'z' 342 | Si vous n'êtes pas sûr du type d'un objet, vous pouvez demander: 343 | >>> type (p) 344 | 345 | Vous pouvez également utiliser isinstance pour vérifier si un objet est une instance d'une classe: 346 | >>> isinstance (p, Point) 347 | Vrai 348 | Si vous n'êtes pas sûr qu'un objet possède un attribut particulier, vous pouvez utiliser la fonction intégrée. 349 | fonction hasattr: 350 | >>> hasattr (p, 'x') 351 | Vrai 352 | >>> hasattr (p, 'z') 353 | Faux 354 | Le premier argument peut être n'importe quel objet. le second argument est une chaîne contenant le nom 355 | de l'attribut. 356 | Vous pouvez également utiliser une instruction try pour voir si l'objet possède les attributs dont vous avez besoin: 357 | try: 358 | x = p.x 359 | except AttributeError: 360 | x = 0 361 | Cette approche peut faciliter l'écriture de fonctions qui fonctionnent avec différents types. plus 362 | sur ce sujet est à venir dans la section 17.9. 363 | 364 | 15.8 365 | 366 | Glossaire 367 | 368 | classe: un type défini par le programmeur. Une définition de classe crée un nouvel objet de classe. 369 | objet de classe: objet contenant des informations sur un type défini par le programmeur. le 370 | Un objet de classe peut être utilisé pour créer des instances du type. 371 | instance: un objet qui appartient à une classe. 372 | instancier: pour créer un nouvel objet. 373 | attribut: une des valeurs nommées associées à un objet. 374 | objet incorporé: objet stocké en tant qu'attribut d'un autre objet. 375 | copie superficielle: pour copier le contenu d'un objet, y compris toute référence à 376 | objets; mis en œuvre par la fonction de copie dans le module de copie. 377 | deep copy: Pour copier le contenu d’un objet ainsi que tout objet incorporé et tout objet 378 | objets intégrés dans eux, et ainsi de suite; mis en œuvre par la fonction deepcopy dans le 379 | module de copie. 380 | diagramme d'objet: diagramme montrant les objets, leurs attributs et les valeurs des attributs. 381 | 382 | 154 383 | 384 | 15.9 385 | 386 | Chapitre 15. Classes et objets 387 | 388 | Des exercices 389 | 390 | Exercice 15.1. Ecrivez une définition pour une classe nommée Circle avec les attributs centre et rayon, 391 | où centre est un objet Point et rayon est un nombre. 392 | Instanciez un objet Circle représentant un cercle dont le centre est (150, 100) et le rayon 75. 393 | Ecrivez une fonction nommée point_in_circle qui prend un cercle et un point et renvoie True si le 394 | Le point se situe dans ou sur la limite du cercle. 395 | Ecrivez une fonction nommée rect_in_circle qui prend un cercle et un rectangle et renvoie True si 396 | le rectangle se situe entièrement dans ou sur la limite du cercle. 397 | Ecrivez une fonction nommée rect_circle_overlap qui prend un cercle et un rectangle et retourne 398 | Vrai si l’un des coins du rectangle se situe à l’intérieur du cercle. Ou comme une version plus difficile, 399 | renvoie True si une partie du rectangle tombe à l'intérieur du cercle. 400 | Solution: http: // thinkpython2. com / code / cercle. py. 401 | Exercice 15.2. Ecrivez une fonction appelée draw_rect qui prend un objet Turtle et un rectangle et 402 | utilise la tortue pour dessiner le rectangle. Voir le chapitre 4 pour des exemples utilisant des objets Tortue. 403 | Ecrivez une fonction appelée draw_circle qui prend une tortue et un cercle et dessine le cercle. 404 | Solution: http: // thinkpython2. com / code / dessiner. py. -------------------------------------------------------------------------------- /ch16Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 16 2 | 3 | Classes et fonctions 4 | Maintenant que nous savons comment créer de nouveaux types, la prochaine étape consiste à écrire des fonctions prenant 5 | des objets définis par le programmeur en tant que paramètres et les renvoyer en tant que résultats. Dans ce chapitre je 6 | présente également le «style de programmation fonctionnelle» et deux nouveaux plans de développement de programmes. 7 | Des exemples de code de ce chapitre sont disponibles à l'adresse http://thinkpython2.com/code/. 8 | Time1.py. Les solutions aux exercices se trouvent à l'adresse http://thinkpython2.com/code/Time1_soln. 9 | py. 10 | 11 | 16.1 12 | 13 | Temps 14 | 15 | Comme autre exemple de type défini par le programmeur, nous allons définir une classe appelée Time qui 16 | enregistre l'heure de la journée. La définition de la classe ressemble à ceci: 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Le diagramme d'état de l'objet Time ressemble à celui de la figure 16.1. 29 | Comme exercice, écrivez une fonction appelée print_time qui prend un objet Time et l’imprime sous 30 | la forme heure: minute: seconde. Astuce: la séquence de formats '% .2d' imprime un entier à l'aide de 31 | au moins deux chiffres, y compris un zéro si nécessaire. 32 | Ecrivez une fonction booléenne appelée is_after qui prend deux objets Time, t1 et t2, et renvoie True si t1 suit t2 chronologiquement et False sinon. Défi: ne pas utiliser un 33 | déclaration if. 34 | 35 | 156 36 | 37 | Chapitre 16. Classes et fonctions 38 | Temps 39 | temps 40 | 41 | heure 42 | 43 | 11 44 | 45 | minute 46 | 47 | 59 48 | 49 | seconde 50 | 51 | 30 52 | 53 | Figure 16.1: Diagramme d'objets. 54 | 55 | 16.2 56 | 57 | Fonctions pures 58 | 59 | Dans les sections suivantes, nous écrirons deux fonctions qui ajoutent des valeurs temporaires. Ils démontrent 60 | deux types de fonctions: les fonctions pures et les modificateurs. Ils présentent également un plan de développement que j’appellerai prototype et patch, qui permet de résoudre un problème complexe en 61 | commençant par un simple prototype et en traitant progressivement les complications. 62 | Voici un prototype simple de add_time: 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | La fonction crée un nouvel objet Time, initialise ses attributs et renvoie une référence au 71 | nouveau objet. Ceci est appelé une fonction pure car elle ne modifie aucun objet 72 | passé comme argument et cela n'a aucun effet, comme afficher une valeur ou obtenir une entrée d'utilisateur, 73 | autre que de retourner une valeur. 74 | Pour tester cette fonction, je vais créer deux objets Time: start contient l’heure de début d’un film, 75 | comme Monty Python et le Saint Graal, et la durée contient la durée du film, 76 | qui est une heure et 35 minutes. 77 | 78 | add_time détermine quand le film sera terminé. 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Le résultat, 10:80:00, pourrait ne pas être ce que vous espériez. Le problème est que 95 | la fonction ne traite pas les cas où le nombre de secondes ou de minutes s’ajoute à 96 | plus de soixante. Lorsque cela se produit, nous devons «porter» les secondes supplémentaires dans la minute 97 | colonne ou les minutes supplémentaires dans la colonne des heures. 98 | Voici une version améliorée: 99 | 100 | 16.3. Modificateurs 101 | 102 | 157 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Bien que cette fonction soit correcte, elle commence à devenir grande. Nous verrons une alternative plus courte 117 | plus tard. 118 | 119 | 16.3 120 | 121 | Modificateurs 122 | 123 | Il est parfois utile qu’une fonction modifie les objets qu’elle récupère en tant que paramètres. Dans ce cas, 124 | les modifications sont visibles pour l'appelant. Les fonctions qui fonctionnent de cette façon sont appelées modificateurs. 125 | 126 | incrément, qui ajoute un nombre donné de secondes à un objet Time, peut être écrit naturellement 127 | en tant que modificateur. Voici un brouillon: 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | La première ligne effectue l'opération de base; le reste traite des cas spéciaux que nous avons 137 | vu avant. 138 | Cette fonction est-elle correcte? Qu'advient-il si les sont secondes plus grandes que soixante? 139 | Dans ce cas, il ne suffit pas de porter une fois; nous devons continuer à le faire jusqu'à time.second est 140 | moins de soixante. Une solution consiste à remplacer les déclarations if par des déclarations while. Cette 141 | rendrait la fonction correcte, mais pas très efficace. Comme exercice, écrivez un c 142 | version d’incrément ne contenant pas de boucles. 143 | Tout ce qui peut être fait avec des modificateurs peut également être fait avec des fonctions pures. En réalité, 144 | certains langages de programmation n'autorisent que des fonctions pures. Il y a des preuves que 145 | les programmes utilisant des fonctions pures sont plus rapides à développer et moins sujets aux erreurs que les programmes 146 | qui utilisent des modificateurs. Mais les modificateurs sont parfois pratiques et les programmes fonctionnels ont tendance à 147 | être moins efficace. 148 | 149 | 158 150 | 151 | Chapitre 16. Classes et fonctions 152 | 153 | En général, je vous recommande d’écrire des fonctions pures chaque fois que cela est raisonnable et 154 | aux modificateurs que s'il existe un avantage convaincant. Cette approche pourrait être appelée un 155 | style de programmation fonctionnel. 156 | En tant qu’exercice, écrivez une version «pure» d’incrément qui crée et retourne une nouvelle objet 157 | plutôt que de modifier le paramètre. 158 | 159 | 16.4 160 | 161 | Prototypage versus planification 162 | 163 | Le plan de développement que je présente s'appelle «prototype et patch». Pour chaque fonction, j’ai écrit un prototype qui a effectué le calcul de base, puis je l’ai testé, en corrigeant 164 | cas d'erreurs en cours de route. 165 | Cette approche peut être efficace, surtout si vous ne comprenez pas encore très bien 166 | le problème. Mais les corrections incrémentielles peuvent générer du code inutilement 167 | compliqué - puisqu'il traite de nombreux cas particuliers - et peu fiable - puisqu'il est difficile de 168 | savoir si vous avez trouvé toutes les erreurs. 169 | Une alternative est le développement conçu, dans lequel une compréhension de haut niveau du problème peut 170 | rendre la programmation beaucoup plus facile. Dans ce cas, l’idée est qu’un objet Time est vraiment 171 | un numéro à trois chiffres en base 60 (voir http://en.wikipedia.org/wiki/Sexagesimal.)! 172 | deuxième attribut est la colonne «Un», l’attribut minute est la «colonne 60» et le 173 | l'attribut hour est la «colonne des trente-six cents». 174 | Quand nous avons écrit add_time et increment, nous faisions effectivement addition en base 60, 175 | c'est pourquoi nous avons dû passer d'une colonne à l'autre. 176 | Cette observation suggère une autre approche du problème: nous pouvons convertir l'objet temps 177 | à des entiers et tirer parti du fait que l'ordinateur sait comment faire 178 | arithmétique entière. 179 | Voici une fonction qui convertit temps en nombres entiers: 180 | 181 | 182 | 183 | 184 | 185 | Et voici une fonction qui convertit un entier en Time (rappelons que divmod divise le premier 186 | argument par le second et retourne le quotient et le reste sous forme de tuple). 187 | 188 | 189 | 190 | 191 | 192 | Vous devrez peut-être réfléchir un peu et exécuter des tests pour vous convaincre que ces fonctions 193 | sont corrects. Une façon de les tester est de vérifier que time_to_int (int_to_time (x)) == x pour 194 | beaucoup de valeurs de x. Ceci est un exemple de contrôle de cohérence. 195 | Une fois que vous êtes convaincu qu'ils sont corrects, vous pouvez les utiliser pour réécrire add_time: 196 | 197 | 198 | 199 | 200 | 201 | 16.5. Débogage 202 | 203 | 159 204 | 205 | Cette version est plus courte que la version originale et plus facile à vérifier. Comme exercice, réécrire 206 | incrément en utilisant time_to_int et int_to_time. 207 | À certains égards, la conversion de la base 60 à la base 10 et au-delà est plus difficile que de simplement traiter avec 208 | temps. La conversion de base est plus abstraite; notre intuition pour gérer les valeurs de temps est meilleure. 209 | Mais si nous avons la perspicacité de traiter les temps comme des nombres de base 60 et de faire l’investissement de 210 | écrivant les fonctions de conversion (time_to_int et int_to_time), nous obtenons un programme qui 211 | est plus court, plus facile à lire et à déboguer, et plus fiable. 212 | Il est également plus facile d'ajouter des fonctionnalités ultérieurement. Par exemple, imaginez soustraire deux fois pour trouver 213 | la durée entre eux. L’approche naïve consisterait à appliquer la soustraction avec 214 | emprunt. L'utilisation des fonctions de conversion serait plus facile et plus probable. 215 | Ironiquement, rendre un problème plus difficile (ou plus général) le facilite (parce qu'il 216 | y a moins de cas spéciaux et moins de risques d'erreur). 217 | 218 | 16,5 219 | 220 | Débogage 221 | 222 | Un objet Time est bien formé si les valeurs de minute et de seconde sont comprises entre 0 et 60 223 | (y compris 0 mais pas 60) et si heure est positive. heure et minute doivent être des valeurs intégrales, 224 | mais nous pourrions permettre à la seconde d'avoir une fraction de partie. 225 | Des conditions telles que celles-ci sont appelées invariants car elles doivent toujours être vraies. Mettre 226 | c'est différent, s'ils ne sont pas vrais, quelque chose a mal tourné. 227 | Écrire du code pour vérifier les invariants peut aider à détecter les erreurs et à en trouver les causes. Par exemple, 228 | vous pourriez avoir une fonction comme valid_time qui prend un objet Time et renvoie False si elle 229 | viole un invariant: 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | Au début de chaque fonction, vous pouvez vérifier les arguments pour vous assurer qu’ils sont 238 | valide: 239 | 240 | 241 | 242 | 243 | 244 | Vous pouvez également utiliser une instruction assert, qui vérifie un invariant donné et déclenche une exception en cas d'échec: 245 | 246 | 247 | 248 | 249 | 250 | 251 | Les instructions assert sont utiles car elles distinguent le code traitant des conditions normales du code vérifiant les erreurs. 252 | 253 | 160 254 | 255 | 16,6 256 | 257 | Chapitre 16. Classes et fonctions 258 | 259 | Glossaire 260 | 261 | prototype et correctif: plan de développement qui consiste à rédiger un brouillon d'un programme, à tester et à corriger les erreurs à mesure qu'elles sont détectées. 262 | développement conçu: un plan de développement qui implique un aperçu de haut niveau de la 263 | problème et plus de planification que le développement incrémental ou le développement du prototype. 264 | fonction pure: fonction qui ne modifie aucun des objets reçus en tant qu'arguments. 265 | La plupart des fonctions pures sont fructueuses. 266 | modificateur: fonction qui modifie un ou plusieurs objets qu’elle reçoit en tant qu’arguments. Plus 267 | de modificateurs sont nuls; c'est-à-dire qu'ils ne retournent aucun. 268 | style de programmation fonctionnel: style de conception de programme dans lequel la plupart des fonctions sont pures. 269 | invariant: une condition qui devrait toujours être vraie lors de l'exécution d'un programme. 270 | assert statement: déclaration qui vérifie une condition et déclenche une exception en cas d'échec. 271 | 272 | 16,7 273 | 274 | Des exercices 275 | 276 | Des exemples de code de ce chapitre sont disponibles à l'adresse http://thinkpython2.com/code/. 277 | Time1.py; les solutions aux exercices sont disponibles sur http://thinkpython2.com/code/ 278 | Time1_soln.py. 279 | Exercice 16.1. Ecrivez une fonction appelée mul_time qui prend un objet Time, un nombre et retourne 280 | un nouvel objet Time contenant le produit de l'heure d'origine et du nombre. 281 | Ensuite, utilisez mul_time pour écrire une fonction prenant un objet Time représentant l'heure de fin. 282 | dans une course, et un nombre qui représente la distance, et retourne un objet Time qui représente le 283 | allure moyenne (temps par mile). 284 | Exercice 16.2. Le module datetime fournit des objets time similaires aux objets time. 285 | dans ce chapitre, mais ils fournissent un riche ensemble de méthodes et d’opérateurs. Lisez la documentation à 286 | http: // docs. python. org / 3 / library / datetime. html. 287 | 1. Utilisez le module datetime pour écrire un programme qui récupère la date du jour et imprime le jour de 288 | la semaine. 289 | 2. Écrivez un programme qui prend un anniversaire en entrée et imprime l’âge de l’utilisateur et le nombre de 290 | jours, heures, minutes et secondes jusqu'à leur prochain anniversaire. 291 | 3. Pour deux personnes nées des jours différents, il y a un jour où l'une est deux fois plus âgée que l'autre. 292 | C’est leur double jour. Ecrivez un programme qui prend deux anniversaires et calcule leur double 293 | jour. 294 | 4. Pour un peu plus de défi, écrivez la version plus générale qui calcule le jour où on 295 | personne est n fois plus vieux que l’autre. 296 | Solution: http: // thinkpython2. com / code / double. py 297 | -------------------------------------------------------------------------------- /ch17Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 17 2 | 3 | Classes et méthodes 4 | Bien que nous utilisions certaines des fonctionnalités orientées objet de Python, les programmes de la 5 | Les deux derniers chapitres ne sont pas vraiment orientés objet, car ils ne représentent pas les relations entre les types définis par le programmeur et les fonctions qui les exploitent. L'étape suivant 6 | consiste à transformer ces fonctions en méthodes qui rendent les relations explicites. 7 | Des exemples de code de ce chapitre sont disponibles à l'adresse http://thinkpython2.com/code/. 8 | Time2.py et les solutions aux exercices se trouvent dans http://thinkpython2.com/code/Point2_ 9 | soln.py. 10 | 11 | 17.1 12 | 13 | Caractéristiques orienté objet 14 | 15 | Python est un langage de programmation orienté objet, ce qui signifie qu'il fournit des fonctionnalités prenant en charge la programmation orientée objet qui présente les caractéristiques suivantes: 16 | • Les programmes incluent des définitions de classe et de méthode. 17 | • La plupart des calculs sont exprimés en termes d'opérations sur des objets. 18 | • Les objets représentent souvent des choses dans le monde réel, et les méthodes correspondent souvent aux 19 | façons dont les choses dans le monde réel interagissent. 20 | Par exemple, la classe Time définie au chapitre 16 correspond à la façon dont les gens enregistrent 21 | le moment de la journée, et les fonctions que nous avons définies correspondent au genre de choses que les gens font 22 | avec les temps. De même, les classes Point et Rectangle du chapitre 15 correspondent aux 23 | concepts mathématiques d'un point et d'un rectangle. 24 | Jusqu'à présent, nous n'avons pas tiré parti des fonctionnalités fournies par Python pour prendre en charge la programmation orientée objet. Ces fonctionnalités ne sont pas strictement nécessaires. la plupart d'entre eux fournissent une 25 | syntaxe alternative pour les choses que nous avons déjà faites. Mais dans de nombreux cas, l'alternative est 26 | plus concis et plus précisément la structure du programme. 27 | Par exemple, dans Time1.py, il n’ya pas de lien évident entre la définition de la classe et 28 | les définitions de fonction qui suivent. En examinant, il apparaît que chaque fonction prend au moins un objet Time comme argument. 29 | 30 | 162 31 | 32 | Chapitre 17. Classes et méthodes 33 | 34 | Cette observation est la motivation pour les méthodes; une méthode est une fonction associée 35 | avec une classe particulière. Nous avons vu des méthodes pour les chaînes, les listes, les dictionnaires et les tuples. Dans 36 | Dans ce chapitre, nous définirons des méthodes pour les types définis par le programmeur. 37 | Les méthodes sont sémantiquement identiques aux fonctions, mais il existe deux différences syntaxiques: 38 | • Les méthodes sont définies dans une définition de classe afin de rendre explicite la relation entre la classe et la méthode. 39 | • La syntaxe utilisée pour appeler une méthode est différente de celle utilisée pour appeler une fonction. 40 | Dans les sections suivantes, nous reprendrons les fonctions des deux chapitres précédents et 41 | transformez-les en méthodes. Cette transformation est purement mécanique. vous pouvez le faire par 42 | en suivant une séquence d'étapes. Si vous êtes à l'aise pour convertir d'un formulaire à un autre, 43 | vous serez en mesure de choisir la meilleure forme pour ce que vous faites. 44 | 45 | 17.2 46 | 47 | imprimer les objets 48 | 49 | Au chapitre 16, nous avons défini une classe nommée Time et à la section 16.1, vous avez écrit une fonction 50 | nommé print_time: 51 | 52 | 53 | 54 | 55 | 56 | Pour appeler cette fonction, vous devez passer un objet Time en argument: 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Pour que print_time soit une méthode, il suffit de déplacer la définition de la fonction dans le 65 | définition de classe. Notez le changement d'indentation. 66 | 67 | 68 | 69 | 70 | Il existe maintenant deux manières d'appeler print_time. La première (et moins commune) consiste à utiliser la 71 | syntaxe de la fonction: 72 | 73 | 74 | 75 | Dans cette utilisation de la notation par points, Time est le nom de la classe et print_time est le nom du 76 | méthode. start est passé en paramètre. 77 | La deuxième manière (plus concise) consiste à utiliser la syntaxe de la méthode: 78 | 79 | 80 | 81 | 82 | 17.3. Un autre exemple 83 | 84 | 163 85 | 86 | Dans cette utilisation de la notation par points, print_time est le nom de la méthode (à nouveau) et start est 87 | l'objet sur lequel la méthode est invoquée, appelé sujet. Tout comme le sujet d'une 88 | phrase est ce que la phrase est sur, le sujet d'une invocation de méthode est ce que le 89 | la méthode est à propos. 90 | Dans la méthode, le sujet est affecté au premier paramètre. Dans ce cas, start est 91 | assigné à temps. 92 | Par convention, le premier paramètre d'une méthode s'appelle self, il serait donc plus courant 93 | d'écrire print_time comme ceci: 94 | 95 | 96 | 97 | 98 | La raison de cette convention est une métaphore implicite: 99 | • La syntaxe d’un appel de fonction, print_time (start), suggère que la fonction est 100 | l'agent actif. Il dit quelque chose comme: “Hey print_time! Voici un objet pour 101 | l'impression." 102 | • En programmation orientée objet, les objets sont les agents actifs. Une invocation de méthode telle que start.print_time () dit «Hey start! S'il vous plaît imprimez vous-même. " 103 | Ce changement de perspective est peut-être plus poli, mais il n’est pas évident qu’il soit utile. dans le 104 | exemples que nous avons vu jusqu'à présent, il se peut que ce ne soit pas le cas. Mais parfois, le transfert de responsabilité du 105 | fonctions sur les objets permet d'écrire des fonctions (ou méthodes) plus polyvalentes, 106 | et facilite la maintenance et la réutilisation du code. 107 | À titre d’exercice, réécrivez time_to_int (section 16.4) en tant que méthode. Vous pourriez être tenté 108 | de réécrire int_to_time comme méthode aussi, mais cela n’a pas vraiment de sens car il y a 109 | ne serait pas un objet pour l'invoquer. 110 | 111 | 17,3 112 | 113 | Un autre exemple 114 | 115 | Voici une version d’incrément (section 16.3) réécrite en tant que méthode: 116 | 117 | 118 | 119 | 120 | 121 | Cette version suppose que time_to_int est écrit en tant que méthode. En outre, notez que c'est un pur 122 | fonction, pas un modificateur. 123 | Voici comment vous appelez incrémentation: 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 164 132 | 133 | Chapitre 17. Classes et méthodes 134 | 135 | Le sujet, commencer, est assigné au premier paramètre, self. L'argument, 1337, obtient 136 | affecté au deuxième paramètre, secondes. 137 | Ce mécanisme peut être déroutant, surtout si vous faites une erreur. Par exemple, si vous 138 | invoquer incrémenter avec deux arguments, vous obtenez: 139 | 140 | 141 | TypeError: increment () prend 2 arguments de position mais 3 ont été donnés 142 | Le message d'erreur est initialement source de confusion, car il n'y a que deux arguments entre parenthèses. Mais le sujet est aussi considéré comme un argument, alors, ensemble, cela fait trois. 143 | Soit dit en passant, un argument de position est un argument qui n’a pas de nom de paramètre; 144 | c'est-à-dire que ce n'est pas un argument de mot clé. Dans cet appel de fonction: 145 | 146 | 147 | perroquet et cage sont positionnels, et dead est un argument de mot clé. 148 | 149 | 17.4 150 | 151 | Un exemple plus compliqué 152 | 153 | La réécriture d’is_after (à partir de la section 16.1) est légèrement plus compliquée car il faut deux 154 | Objets temporels en tant que paramètres. Dans ce cas, il est classique de nommer le premier paramètre self 155 | et le second paramètre other: 156 | 157 | 158 | 159 | 160 | Pour utiliser cette méthode, vous devez l'invoquer sur un objet et transmettre l'autre en tant qu'argument: 161 | 162 | 163 | 164 | Une bonne chose à propos de cette syntaxe est qu’elle se lit presque comme en anglais: “end is after start?” 165 | 166 | 17,5 167 | 168 | La méthode init 169 | 170 | La méthode init (abréviation pour “initialisation”) est une méthode spéciale qui est invoquée lorsqu’un 171 | objet est instancié. Son nom complet est __init__ (deux caractères de soulignement, suivis de 172 | init, puis deux autres underscores). Une méthode init pour la classe Time pourrait ressembler à 173 | ceci: 174 | 175 | 176 | 177 | 178 | 179 | 180 | Il est courant que les paramètres de __init__ aient les mêmes noms que les attributs. le 181 | déclaration 182 | 183 | 184 | 185 | 17.6. La méthode __str__ 186 | 187 | 165 188 | 189 | stocke la valeur du paramètre hour en tant qu'attribut de self. 190 | Les paramètres sont facultatifs. Par conséquent, si vous appelez Time sans arguments, vous obtenez les valeurs 191 | par défaut. 192 | 193 | 194 | 195 | 196 | Si vous fournissez un argument, il remplace heure: 197 | 198 | 199 | 200 | 201 | Si vous fournissez deux arguments, ils ont priorité sur heure et minute. 202 | 203 | 204 | 205 | 206 | Et si vous fournissez trois arguments, ils remplacent les trois valeurs par défaut. 207 | En tant qu’exercice, écrivez une méthode init pour la classe Point qui prend x et y comme facultatif. 208 | paramètres et les affecte aux attributs correspondants. 209 | 210 | 17,6 211 | 212 | La méthode __str__ 213 | 214 | __str__ est une méthode spéciale, telle que __init__, qui est supposée renvoyer une représentation sous forme de chaîne d'un objet. 215 | Par exemple, voici une méthode str pour les objets Time: 216 | 217 | 218 | 219 | 220 | Lorsque vous imprimez un objet, Python appelle la méthode str: 221 | 222 | 223 | 224 | 225 | Quand j'écris un nouveau cours, je commence presque toujours par écrire __init__, ce qui facilite la tâche. 226 | pour instancier des objets, et __str__, ce qui est utile pour le débogage. 227 | En tant qu’exercice, écrivez une méthode str pour la classe Point. Créez un objet Point et imprimez-le. 228 | 229 | 17,7 230 | 231 | Surcharge de l'opérateur 232 | 233 | En définissant d’autres méthodes spéciales, vous pouvez spécifier le comportement des opérateurs sur 234 | types définis par le programmeur. Par exemple, si vous définissez une méthode nommée __add__ pour le 235 | Classe Time, vous pouvez utiliser l'opérateur + sur les objets Time. 236 | Voici à quoi pourrait ressembler la définition: 237 | 238 | 166 239 | 240 | Chapitre 17. Classes et méthodes 241 | 242 | 243 | 244 | 245 | 246 | Et voici comment vous pouvez l'utiliser: 247 | 248 | 249 | 250 | 251 | 252 | Lorsque vous appliquez l'opérateur + aux objets Time, Python appelle __add__. Quand vous imprimez 253 | le résultat, Python invoque __str__. Donc, il se passe beaucoup de choses dans les coulisses! 254 | Changer le comportement d’un opérateur pour qu’il fonctionne avec les types définis par le programmeur est 255 | opérateur appelé surcharge. Pour chaque opérateur de Python, il existe une méthode spéciale correspondante, telle que __add__. Pour plus de détails, voir http://docs.python.org/3/reference/ 256 | datamodel.html # specialnames. 257 | En tant qu’exercice, écrivez une méthode add pour la classe Point. 258 | 259 | 17,8 260 | 261 | Envoi type 262 | 263 | Dans la section précédente, nous avons ajouté deux objets Time, mais vous pouvez également ajouter un objet. 264 | entier à un objet Time. Voici une version de __add__ qui vérifie le type de 265 | other et appelle add_time ou increment: 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | La fonction intégrée isinstance prend une valeur et un objet de classe et renvoie True si le 280 | valeur est une instance de la classe. 281 | Si other est un objet Time, __add__ appelle add_time. Sinon, il suppose que le paramètre est un nombre et appelle incrémenter. Cette opération s'appelle une répartition basée sur un type. 282 | car il distribue le calcul à différentes méthodes en fonction du type des arguments. 283 | Voici des exemples qui utilisent l'opérateur + avec différents types: 284 | 285 | 17.9. Polymorphisme 286 | 287 | 167 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | Malheureusement, cette mise en œuvre de l'addition n'est pas commutative. Si l'entier est le 296 | premier opérande, vous obtenez 297 | 298 | 299 | TypeError: type (s) d'opérande non pris en charge pour +: 'int' et 'instance' 300 | Le problème est qu'au lieu de demander à l'objet Time d'ajouter un entier, Python demande à 301 | entier pour ajouter un objet Time, et il ne sait pas comment. Mais il existe une solution intelligente pour cela 302 | problème: la méthode spéciale __radd__, qui signifie “right-add add”. Cette méthode 303 | est invoqué lorsqu'un objet Time apparaît à droite de l'opérateur +. Ici se trouve le 304 | définition: 305 | 306 | # à l'intérieur de la classe 307 | 308 | 309 | Et voici comment cela est utilisé: 310 | 311 | 312 | 313 | En tant qu’exercice, écrivez une méthode add pour Points qui fonctionne soit avec un objet Point, soit avec un objet Point. 314 | tuple: 315 | • Si le deuxième opérande est un point, la méthode doit retourner un nouveau point dont x 316 | coordonnée est la somme des coordonnées x des opérandes, et de même pour les 317 | coordonnées y. 318 | • Si le deuxième opérande est un tuple, la méthode doit ajouter le premier élément du tuple. 319 | à la coordonnée x et le deuxième élément à la coordonnée y, et retourne un nouveau 320 | Point avec le résultat. 321 | 322 | 17,9 323 | 324 | Polymorphisme 325 | 326 | La répartition par type est utile lorsque cela est nécessaire, mais (heureusement), ce n'est pas toujours nécessaire. Vous pouvez souvent l’éviter en écrivant des fonctions qui fonctionnent correctement pour les arguments avec 327 | différents types. 328 | La plupart des fonctions que nous avons écrites pour les chaînes fonctionnent également pour d'autres types de séquence. Par exemple, dans la section 11.2, nous avons utilisé un histogramme pour compter le nombre de fois que chaque lettre apparaît dans 329 | un mot. 330 | 331 | histogramme (s): 332 | d = dict () 333 | pour c en s: 334 | si c pas dans d: 335 | d [c] = 1 336 | 337 | 168 338 | 339 | Chapitre 17. Classes et méthodes 340 | 341 | autre: 342 | d [c] = d [c] +1 343 | retour d 344 | Cette fonction fonctionne également pour les listes, les n-uplets et même les dictionnaires, à condition que les éléments de 345 | s sont hashable, ils peuvent donc être utilisés comme clés dans d. 346 | >>> t = ['spam', 'oeuf', 'spam', 'spam', 'bacon', 'spam'] 347 | >>> histogramme (t) 348 | {'bacon': 1, 'oeuf': 1, 'spam': 4} 349 | Les fonctions qui fonctionnent avec plusieurs types sont appelées polymorphes. Le polymorphisme peut faciliter la réutilisation du code. Par exemple, la somme de la fonction intégrée, qui ajoute les éléments d’un 350 | sequence, fonctionne tant que les éléments de la séquence supportent l’ajout. 351 | Puisque les objets Time fournissent une méthode add, ils fonctionnent avec sum: 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | En général, si toutes les opérations d’une fonction fonctionnent avec un type donné, la fonction 360 | fonctionne avec ce type. 361 | Le meilleur type de polymorphisme est le type involontaire, où vous découvrez qu'une fonction que vous avez déjà écrite peut être appliquée à un type que vous n'avez jamais planifié. 362 | 363 | 17h10 364 | 365 | Débogage 366 | 367 | Il est légal d’ajouter des attributs à des objets à tout moment de l’exécution d’un programme, mais si 368 | vous avez des objets du même type qui n'ont pas les mêmes attributs, il est facile de faire 369 | des erreurs. Il est considéré comme une bonne idée d’initialiser tous les attributs d’un objet dans le 370 | méthode. 371 | Si vous n'êtes pas sûr qu'un objet possède un attribut particulier, vous pouvez utiliser la fonction intégrée 372 | hasattr (voir section 15.7). 373 | Une autre façon d'accéder aux attributs est la fonction intégrée vars, qui prend un objet et 374 | renvoie un dictionnaire qui associe des noms d'attributs (sous forme de chaînes) à leurs valeurs: 375 | 376 | 377 | 378 | 379 | À des fins de débogage, il peut être utile de garder cette fonction à portée de main: 380 | 381 | 382 | 383 | print_attributes parcourt le dictionnaire et affiche chaque nom d'attribut et sa valeur correspondante. 384 | La fonction intégrée getattr prend un objet et un nom d'attribut (sous forme de chaîne) et renvoie 385 | la valeur de l'attribut. 386 | 387 | 17.11. Interface et implémentation 388 | 389 | 17.11 390 | 391 | 169 392 | 393 | Interface et implémentation 394 | 395 | L’un des objectifs de la conception orientée objet est de rendre le logiciel plus facile à gérer, ce qui 396 | signifie que vous pouvez continuer à faire fonctionner le programme lorsque d’autres éléments du système changent, et 397 | modifier le programme pour répondre aux nouvelles exigences. 398 | Un principe de conception permettant d’atteindre cet objectif consiste à séparer les interfaces des implémentations. Pour les objets, cela signifie que les méthodes fournies par une classe ne doivent pas dépendre 399 | sur la façon dont les attributs sont représentés. 400 | Par exemple, dans ce chapitre, nous avons développé une classe qui représente une heure de la journée. Les méthodes 401 | fournis par cette classe incluent time_to_int, is_after et add_time. 402 | Nous pourrions mettre en œuvre ces méthodes de plusieurs manières. Les détails de la mise en œuvre 403 | dépend de la façon dont nous représentons le temps. Dans ce chapitre, les attributs d’un objet Time sont heure, 404 | minute et seconde. 405 | Comme alternative, nous pourrions remplacer ces attributs par un seul entier représentant le 406 | nombre de secondes depuis minuit. Cette implémentation ferait que certaines méthodes, comme 407 | is_after, plus facile à écrire, mais rend les autres méthodes plus difficiles. 408 | Après avoir déployé une nouvelle classe, vous découvrirez peut-être une meilleure implémentation. Si d'autres parties 409 | du programme utilisent votre classe, il peut être fastidieux et sujet aux erreurs de changer 410 | L'interface. 411 | Mais si vous avez soigneusement conçu l’interface, vous pouvez modifier l’implémentation sans 412 | modification de l'interface, ce qui signifie que les autres parties du programme ne doivent pas être modifiées. 413 | 414 | 17.12 415 | 416 | Glossaire 417 | 418 | langage orienté objet: langage offrant des fonctionnalités, telles que des types et des méthodes définis par le programmeur, facilitant la programmation orientée objet. 419 | programmation orientée objet: style de programmation dans lequel les données et les opérations 420 | qui le manipulent sont organisés en classes et méthodes. 421 | méthode: fonction définie dans une définition de classe et appelée sur des instances de 422 | cette classe. 423 | subject: L'objet sur lequel une méthode est invoquée. 424 | argument positional: un argument qui n'inclut pas un nom de paramètre, donc ce n'est pas un 425 | argument de mot clé. 426 | surcharge de l’opérateur: Changer le comportement d’un opérateur comme + pour qu’il fonctionne avec 427 | type défini par le programmeur. 428 | répartition basée sur le type: modèle de programmation qui vérifie le type d'un opérande et appelle différentes fonctions pour différents types. 429 | polymorphe: se rapportant à une fonction pouvant fonctionner avec plusieurs types. 430 | masquage d'informations: principe selon lequel l'interface fournie par un objet ne doit pas dépendre de sa mise en oeuvre, en particulier de la représentation de ses attributs. 431 | 432 | 170 433 | 434 | 17.13 435 | 436 | Chapitre 17. Classes et méthodes 437 | 438 | Des exercices 439 | 440 | Exercice 17.1. Téléchargez le code de ce chapitre à partir de http: // thinkpython2. com / code / 441 | Time2. py. Changez les attributs de Time en un entier représentant les secondes depuis minuit. Modifiez ensuite les méthodes (et la fonction int_to_time) pour utiliser la nouvelle implémentation. Vous ne devriez pas avoir à modifier le code de test dans main. Lorsque vous avez terminé, la sortie devrait 442 | être le même qu'avant. Solution: http: // thinkpython2. com / code / Time2_ soln. py. 443 | Exercice 17.2. Cet exercice est un récit édifiant sur l’un des exercices les plus courants et difficiles à 444 | trouver, des erreurs en Python. Ecrivez une définition pour une classe nommée Kangaroo avec les méthodes suivantes: 445 | 1. Une méthode __init__ qui initialise un attribut nommé pouch_contents à une liste vide. 446 | 2. Une méthode nommée put_in_pouch qui prend un objet de tout type et l’ajoute à 447 | pouch_contents. 448 | 3. Une méthode __str__ qui renvoie une représentation sous forme de chaîne de l'objet Kangourou et du contenu de la poche. 449 | Testez votre code en créant deux objets Kangourou, en les affectant à des variables nommées kanga et 450 | roo, puis en rajoutant au contenu de la poche de kanga. 451 | Téléchargez http: // thinkpython2. com / code / BadKangaroo. py. Il contient une solution à la 452 | problème précédent avec un gros bug méchant. Trouvez et corrigez le bogue. 453 | Si vous êtes bloqué, vous pouvez télécharger http: // thinkpython2. com / code / GoodKangaroo. py, 454 | ce qui explique le problème et démontre une solution. -------------------------------------------------------------------------------- /ch19Fr.txt: -------------------------------------------------------------------------------- 1 | Chapitre 19 2 | 3 | Les goodies 4 | Un de mes objectifs de ce livre a été de vous apprendre le moins possible de Python. Quand 5 | il y avait deux façons de faire quelque chose, j'ai choisi l'une et évité de mentionner l'autre. Ou 6 | parfois, je mets le second dans un exercice. 7 | Maintenant, je veux revenir sur certains des bons éléments qui ont été laissés pour compte. Python fournit un 8 | nombre de fonctionnalités qui ne sont pas vraiment nécessaires - vous pouvez écrire du bon code sans elles - 9 | mais avec eux, vous pouvez parfois écrire du code plus concis, lisible ou efficace, et 10 | parfois tous les trois. 11 | 12 | 19.1 13 | 14 | Expressions conditionnelles 15 | 16 | Nous avons vu des déclarations conditionnelles à la section 5.4. Les instructions conditionnelles sont souvent utilisées pour 17 | choisissez l'une des deux valeurs; par exemple: 18 | 19 | 20 | 21 | 22 | 23 | Cette déclaration vérifie si x est positif. Si tel est le cas, il calcule math.log. Si non, math.log 24 | soulèverait un ValueError. Pour éviter d’arrêter le programme, nous générons un «NaN», qui est 25 | une valeur spéciale en virgule flottante qui représente «Pas un nombre». 26 | Nous pouvons écrire cette déclaration de manière plus concise en utilisant une expression conditionnelle: 27 | 28 | 29 | Vous pouvez presque lire cette ligne comme en anglais: «y obtient log-x si x est supérieur à 0; sinon on 30 | obtient NaN ”. 31 | Les fonctions récursives peuvent parfois être réécrites à l'aide d'expressions conditionnelles. Par exemple, voici une version récursive factorielle: 32 | 33 | 34 | 35 | 36 | 37 | 184 38 | 39 | Chapitre 19. Les goodies 40 | 41 | Nous pouvons le réécrire comme ceci: 42 | 43 | 44 | 45 | Une autre utilisation des expressions conditionnelles est la gestion des arguments facultatifs. Par exemple, ici 46 | est la méthode init de GoodKangaroo (voir l'exercice 17.2): 47 | 48 | 49 | 50 | 51 | 52 | 53 | Nous pouvons réécrire celui-ci comme ceci: 54 | 55 | 56 | 57 | 58 | En général, vous pouvez remplacer une instruction conditionnelle par une expression conditionnelle si 59 | les branches contiennent des expressions simples qui sont soit renvoyées, soit attribuées à la même variable. 60 | 61 | 19.2 62 | 63 | 64 | 65 | List comprehensions 66 | 67 | Dans la section 10.7, nous avons vu la carte et les modèles de filtrage. Par exemple, cette fonction prend une liste 68 | des chaînes, mappe la méthode des chaînes en majuscule avec les éléments et renvoie une nouvelle liste de 69 | string: 70 | 71 | 72 | 73 | 74 | 75 | 76 | Nous pouvons écrire ceci de manière plus concise en utilisant une liste de compréhension: 77 | 78 | 79 | 80 | Les opérateurs de parenthèse indiquent que nous construisons une nouvelle liste. L'expression à l'intérieur 81 | des crochets spécifient les éléments de la liste et la clause for indique quelle séquence 82 | nous traversons. 83 | La syntaxe d’une compréhension de liste est un peu délicate car la variable de boucle, s dans cette 84 | exemple, apparaît dans l'expression avant d'arriver à la définition. 85 | Les compréhensions de liste peuvent également être utilisées pour le filtrage. Par exemple, cette fonction ne sélectionne que 86 | les éléments de t qui sont en majuscule, et retourne une nouvelle liste: 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 19.3. Expressions générateur 96 | 97 | 185 98 | 99 | Nous pouvons le réécrire en utilisant une liste de compréhension 100 | 101 | 102 | 103 | La compréhension des listes est concise et facile à lire, du moins pour les expressions simples. Et ils 104 | sont généralement plus rapides que leurs équivalents pour les boucles, parfois beaucoup plus rapidement. Donc si tu es en colère 105 | contre moi pour ne pas les mentionner plus tôt, je comprends. 106 | Mais, pour ma défense, les compréhensions de liste sont plus difficiles à déboguer car vous ne pouvez pas mettre une empreinte 107 | de déclaration à l'intérieur de la boucle. Je suggère que vous les utilisiez seulement si le calcul est assez 108 | simple pour que vous réussissiez bien la première fois. Et pour les débutants, cela signifie jamais. 109 | 110 | 19.3 111 | 112 | Expressions générateur 113 | 114 | Les expressions générateur sont similaires aux compréhensions de liste, mais avec des parenthèses au lieu de 115 | crochets: 116 | 117 | 118 | 119 | 120 | Le résultat est un objet générateur qui sait comment parcourir une séquence de valeurs. Mais 121 | contrairement à une compréhension de liste, il ne calcule pas les valeurs en une seule fois; il attend d'être demandé. 122 | La fonction intégrée obtient ensuite la valeur suivante du générateur: 123 | 124 | 125 | 126 | 127 | Lorsque vous arrivez à la fin de la séquence, déclenche ensuite une exception StopIteration. Vous pouvez 128 | utilisez également une boucle for pour parcourir les valeurs: 129 | 130 | 131 | 132 | 133 | 134 | 135 | L'objet générateur garde une trace de sa position dans la séquence, ainsi la boucle for est reprise 136 | 137 | 138 | 139 | Les expressions de générateur sont souvent utilisées avec des fonctions telles que sum, max et min: 140 | 141 | 142 | 143 | 19.4 all 144 | Python fournit une fonction intégrée, any, qui prend une séquence de valeurs booléennes et renvoie True si l'une de ces valeurs est True. Cela fonctionne sur les listes: 145 | 146 | 186 147 | 148 | Chapitre 19. Les goodies 149 | 150 | 151 | 152 | Mais il est souvent utilisé avec des expressions de générateur: 153 | 154 | 155 | 156 | Cet exemple n’est pas très utile car il fait la même chose que l’opérateur in. Mais nous 157 | pourrait utiliser n’importe lequel pour réécrire certaines des fonctions de recherche décrites à la section 9.3. Par exemple, 158 | nous pourrions écrire évite comme ceci: 159 | 160 | 161 | 162 | 163 | 164 | L’utilisation de toute expression avec un générateur est efficace car elle s’arrête immédiatement si elle trouve une 165 | valeur True, il n’est donc pas nécessaire d’évaluer la séquence entière. 166 | Python fournit une autre fonction intégrée, all, qui renvoie True si chaque élément de la 167 | la séquence est vraie. En guise d’exercice, utilisez all pour réécrire le fichier uses_all de la section 9.3. 168 | 169 | 19,5 170 | 171 | Ensembles 172 | 173 | Dans la section 13.6, j’utilise des dictionnaires pour trouver les mots qui apparaissent dans un document mais pas dans une 174 | liste de mots. La fonction que j’ai écrite prend d1, qui contient les mots du document en tant que 175 | clés, et d2, qui contient la liste des mots. Il retourne un dictionnaire qui contient les clés 176 | à partir de d1 qui ne sont pas en d2. 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | Dans tous ces dictionnaires, les valeurs sont None car nous ne les utilisons jamais. En conséquence, nous 185 | prenons de l'espace de stockage. 186 | Python fournit un autre type intégré, appelé set, qui se comporte comme une collection de clés de dictionnaire sans valeur. L'ajout d'éléments à un ensemble est rapide; il en va de vérification de l'adhésion. 187 | Les sets fournissent des méthodes et des opérateurs permettant de calculer des opérations d’ensemble communes. 188 | Par exemple, la soustraction d’ensembles est disponible sous forme de méthode appelée différence ou d’opérateur, 189 | - Donc, nous pouvons réécrire soustraire comme ceci: 190 | 191 | 192 | 193 | Le résultat est un ensemble à la place d'un dictionnaire, mais pour les opérations comme l'itération, le comportement est 194 | le même. 195 | Certains des exercices de ce livre peuvent être réalisés de manière concise et efficace avec des ensembles. Pour 196 | Par exemple, voici une solution à has_duplicates, de l’exercice 10.7, qui utilise un dictionnaire: 197 | 198 | 19.6. Des compteurs 199 | 200 | 187 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | Lorsqu'un élément apparaît pour la première fois, il est ajouté au dictionnaire. Si le même élément 210 | apparaît à nouveau, la fonction retourne True. 211 | En utilisant des ensembles, nous pouvons écrire la même fonction comme ceci: 212 | 213 | 214 | 215 | Un élément ne peut apparaître qu'une seule fois dans un set. Ainsi, si un élément de t apparaît plus d'une fois, la 216 | l'ensemble sera plus petit que t. S'il n'y a pas de doublons, l'ensemble aura la même taille que t. 217 | Nous pouvons également utiliser des ensembles pour faire certains des exercices du chapitre 9. Par exemple, voici une version 218 | de uses_only avec une boucle: 219 | 220 | 221 | 222 | 223 | 224 | 225 | uses_only vérifie si toutes les lettres du mot sont disponibles. Nous pouvons le réécrire comme ceci: 226 | 227 | 228 | L’opérateur <= vérifie si un ensemble est un sous-ensemble ou un autre, y compris la possibilité que 229 | ils sont égaux, ce qui est vrai si toutes les lettres du mot apparaissent dans disponible. 230 | En tant qu’exercice, réécrire évite d’utiliser des sets. 231 | 232 | 19,6 233 | 234 | Des compteurs 235 | 236 | Un compteur est comme un set, sauf que si un élément apparaît plusieurs fois, le compteur 237 | garde la trace de combien de fois il apparaît. Si vous connaissez l'idée mathématique 238 | d’un multiset, un compteur est un moyen naturel de représenter un multiset. 239 | Counter est défini dans un module standard appelé collections, vous devez donc l'importer. Vous 240 | pouvez initialiser un compteur avec une chaîne, une liste ou tout autre support prenant en charge l'itération: 241 | 242 | 243 | 244 | 245 | 246 | Les compteurs se comportent comme des dictionnaires à bien des égards; ils mappent de chaque clé au nombre de 247 | fois il apparaît. Comme dans les dictionnaires, les clés doivent être utilisables. 248 | Contrairement aux dictionnaires, les compteurs ne déclenchent pas d’exception si vous accédez à un élément qui 249 | apparaît pas. Au lieu de cela, ils retournent 0: 250 | 251 | 188 252 | 253 | Chapitre 19. Les goodies 254 | 255 | 256 | 257 | Nous pouvons utiliser des compteurs pour réécrire is_anagram à partir de l'exercice 10.6: 258 | 259 | 260 | 261 | Si deux mots sont des anagrammes, ils contiennent les mêmes lettres avec les mêmes comptes, donc leur 262 | compteurs sont équivalents. 263 | Les compteurs fournissent des méthodes et des opérateurs pour effectuer des opérations similaires à des ensembles, telles que l'addition, la soustraction, l'union et l'intersection. Et ils fournissent une méthode souvent utile, 264 | most_common, qui retourne une liste de paires valeur-fréquence, triées du plus commun au 265 | moins: 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 19,7 276 | 277 | defaultdict 278 | 279 | Le module collections fournit également defaultdict, qui est comme un dictionnaire, sauf que 280 | Si vous accédez à une clé inexistante, elle peut générer une nouvelle valeur à la volée. 281 | Lorsque vous créez un defaultdict, vous fournissez une fonction permettant de créer de nouvelles valeurs. Une 282 | fonction utilisée pour créer des objets est parfois appelée une fabrique. Les fonctions intégrées qui 283 | créer des listes, des ensembles et d'autres types peuvent être utilisés en tant qu'usines: 284 | 285 | 286 | 287 | Notez que l'argument est list, qui est un objet de classe, et non list (), qui est une nouvelle liste. 288 | La fonction que vous fournissez n’est pas appelée à moins d’accéder à une clé inexistante. 289 | 290 | 291 | 292 | 293 | La nouvelle liste, que nous appelons t, est également ajoutée au dictionnaire. Donc, si on modifie t, le 294 | le changement apparaît en d: 295 | 296 | 297 | 298 | Si vous faites un dictionnaire de listes, vous pouvez souvent écrire un code plus simple en utilisant defaultdict. 299 | Dans ma solution à l'exercice 12.2, que vous pouvez obtenir à l'adresse http://thinkpython2.com/code/ 300 | anagram_sets.py, je crée un dictionnaire qui mappe une chaîne de lettres triée à la liste de 301 | mots qui peuvent être orthographiés avec ces lettres. Par exemple, "opst" correspond à la liste ["opts", 302 | 'post', 'pots', 'spot', 'stop', 'tops']. 303 | Voici le code original: 304 | 305 | 19.8. Tuples nommés 306 | 307 | 189 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | Ceci peut être simplifié en utilisant setdefault, que vous avez peut-être utilisé dans l'exercice 11.2: 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | Cette solution a l’inconvénient de créer à chaque fois une nouvelle liste, qu’elle soit ou non 328 | c'est nécessaire. Pour les listes, ce n’est pas grave, mais si la fonction d’usine est compliquée, il se peut 329 | être. 330 | Nous pouvons éviter ce problème et simplifier le code en utilisant un defaultdict: 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | Ma solution à l'exercice 18.3, que vous pouvez télécharger à partir de http://thinkpython2.com/ 340 | code / PokerHandSoln.py, utilise setdefault dans la fonction has_straightflush. Cette solution a l’inconvénient de créer un objet Hand à chaque fois dans la boucle, que ce soit 341 | nécessaire ou pas. À titre d'exercice, réécrivez-le à l'aide d'un defaultdict. 342 | 343 | 19.8 344 | 345 | Named Tuples 346 | 347 | De nombreux objets simples sont essentiellement des collections de valeurs liées. Par exemple, le point 348 | L'objet défini au chapitre 15 contient deux nombres, x et y. Lorsque vous définissez une classe comme 349 | ceci commence généralement avec une méthode init et une méthode str: 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 190 359 | 360 | Chapitre 19. Les goodies 361 | 362 | C'est beaucoup de code pour transmettre une petite quantité d'informations. Python fournit un plus 363 | manière concise de dire la même chose: 364 | 365 | 366 | 367 | Le premier argument est le nom de la classe que vous voulez créer. La seconde est une liste des 368 | attributs Les objets Point doivent avoir, comme des chaînes. La valeur de retour de namedtuple est une classe 369 | objet: 370 | 371 | 372 | 373 | Point fournit automatiquement des méthodes telles que __init__ et __str__ afin que vous n'ayez pas à 374 | écris-les. 375 | Pour créer un objet Point, vous utilisez la classe Point en tant que fonction: 376 | 377 | >>> p = Point (1, 2) 378 | >>> p 379 | Point (x = 1, y = 2) 380 | La méthode init assigne les arguments aux attributs en utilisant les noms que vous avez fournis. le 381 | La méthode str affiche une représentation de l'objet Point et de ses attributs. 382 | Vous pouvez accéder aux éléments du tuple nommé par leur nom: 383 | 384 | >>> p.x, p.y 385 | (1, 2) 386 | Mais vous pouvez aussi traiter un tuple nommé comme un tuple: 387 | 388 | >>> p [0], p [1] 389 | (1, 2) 390 | >>> x, y = p 391 | >>> x, y 392 | (1, 2) 393 | Les n-uplets nommés offrent un moyen rapide de définir des classes simples. L'inconvénient est aussi simple 394 | Les cours ne restent pas toujours simples. Vous pourrez décider plus tard d’ajouter des méthodes 395 | à un tuple nommé. Dans ce cas, vous pouvez définir une nouvelle classe qui hérite de la classe nommée 396 | tuple: 397 | 398 | 399 | 400 | Ou vous pouvez passer à une définition de classe conventionnelle. 401 | 402 | 19,9 403 | 404 | Rassemblement des arguments de mots clés 405 | 406 | Dans la section 12.4, nous avons vu comment écrire une fonction qui regroupe ses arguments dans un tuple: 407 | 408 | 409 | 410 | Vous pouvez appeler cette fonction avec un nombre quelconque d’arguments de position (c’est-à-dire des arguments 411 | n'ayant pas de mots-clés): 412 | 413 | 19.10. Glossaire 414 | 415 | 191 416 | 417 | 418 | 419 | Mais l’opérateur * ne collecte pas les arguments de mots clés: 420 | 421 | 422 | 423 | Pour rassembler des arguments de mots-clés, vous pouvez utiliser l'opérateur **: 424 | 425 | 426 | 427 | Vous pouvez appeler le paramètre de collecte de mots-clés comme bon vous semble, mais kwargs est une méthode courante. 428 | choix. Le résultat est un dictionnaire qui associe des mots-clés à des valeurs: 429 | 430 | 431 | 432 | Si vous avez un dictionnaire de mots-clés et de valeurs, vous pouvez utiliser l'opérateur scatter, ** pour 433 | appeler une fonction: 434 | 435 | 436 | 437 | 438 | Sans l’opérateur scatter, la fonction traiterait d comme un argument de position unique, donc 439 | il assignerait d à x et se plaindrait car il n’y avait rien à assigner à y: 440 | 441 | 442 | 443 | 444 | 445 | 446 | Lorsque vous travaillez avec des fonctions comportant un grand nombre de paramètres, il est souvent 447 | utile pour créer et faire circuler des dictionnaires qui spécifient les options fréquemment utilisées. 448 | 449 | 19.10 450 | 451 | Glossaire 452 | 453 | expression conditionnelle: expression qui possède l'une des deux valeurs, en fonction d'une condition. 454 | liste de compréhension: Une expression avec une boucle for entre crochets qui donne une nouvelle 455 | liste. 456 | expression de générateur: Expression avec une boucle for entre parenthèses qui génère un objet générateur. 457 | multiset: entité mathématique représentant un mappage entre les éléments d'un ensemble 458 | et le nombre de fois où ils apparaissent. 459 | factory: Une fonction, généralement passée en paramètre, utilisée pour créer des objets. 460 | 461 | 192 462 | 463 | Chapitre 19. Les goodies 464 | 465 | 19.11 466 | 467 | Des exercices 468 | 469 | Exercice 19.1. Ce qui suit est une fonction qui calcule le coefficient binomial de manière récursive. 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | Réécrivez le corps de la fonction en utilisant des expressions conditionnelles imbriquées. 484 | Une remarque: cette fonction n’est pas très efficace car elle finit par calculer les mêmes valeurs et 485 | plus. Vous pourriez le rendre plus efficace en mémoisant (voir Section 11.6). Mais vous constaterez que c’est 486 | plus difficile à mémoriser si vous écrivez en utilisant des expressions conditionnelles. -------------------------------------------------------------------------------- /ch20FrA.txt: -------------------------------------------------------------------------------- 1 | Annexe A Débogage 2 | 3 | Lors du débogage, vous devez distinguer différents types d’erreurs afin de les localiser plus rapidement: 4 | 5 | Les erreurs de syntaxe sont découvertes par l'interpréteur lors de la traduction du code source en code octet. Ils indiquent qu'il y a quelque chose qui cloche dans la structure du programme. Exemple: L'omission des deux points à la fin d'une instruction def génère le message quelque peu redondant . 6 | Les erreurs d'exécution sont générées par l'interpréteur en cas de problème pendant l'exécution du programme. La plupart des messages d'erreur d'exécution incluent des informations sur l'emplacement de l'erreur et les fonctions exécutées. Exemple: une récursion infinie provoque éventuellement l'erreur d'exécution . 7 | Les erreurs sémantiques sont des problèmes avec un programme qui s'exécute sans produire de messages d'erreur mais ne fait pas ce qui est bien. Exemple: une expression peut ne pas être évaluée dans l'ordre prévu, ce qui donnerait un résultat incorrect. 8 | La première étape du débogage consiste à déterminer le type d'erreur à traiter. Bien que les sections suivantes soient organisées par type d'erreur, certaines techniques sont applicables dans plusieurs situations. 9 | 10 | A.1 Erreurs de syntaxe 11 | 12 | Les erreurs de syntaxe sont généralement faciles à corriger une fois que vous avez compris ce qu’elles sont. Malheureusement, les messages d'erreur ne sont souvent pas utiles. Les messages les plus courants sont et , qui ne sont ni l'un ni l'autre très informatifs. 13 | 14 | D'autre part, le message vous indique où le problème s'est produit dans le programme. En fait, cela vous indique où Python a remarqué un problème, qui ne correspond pas nécessairement à l'erreur. Parfois, l'erreur est antérieure à l'emplacement du message d'erreur, souvent sur la ligne précédente. 15 | 16 | Si vous construisez le programme progressivement, vous devriez avoir une bonne idée de l'emplacement de l'erreur. Ce sera dans la dernière ligne que vous avez ajoutée. 17 | 18 | Si vous copiez du code d’un livre, commencez par comparer votre code avec celui du livre avec le plus grand soin. Vérifiez chaque personnage. Dans le même temps, rappelez-vous que le livre est peut-être faux, donc si vous voyez quelque chose qui ressemble à une erreur de syntaxe, c'est peut-être le cas. 19 | 20 | Voici quelques moyens d'éviter les erreurs de syntaxe les plus courantes: 21 | 22 | Assurez-vous de ne pas utiliser de mot clé Python pour un nom de variable. 23 | Vérifiez que vous avez deux points à la fin de l'en-tête de chaque instruction composée, y compris les instructions for, while, if et def. 24 | Assurez-vous que toutes les chaînes du code ont des guillemets correspondants. Assurez-vous que tous les guillemets sont des «guillemets droits» et non des «guillemets bouclés». 25 | Si vous avez des chaînes multilignes avec des guillemets triples (simples ou doubles), assurez-vous d'avoir terminé la chaîne correctement. Une chaîne non terminée peut provoquer une erreur de jeton non valide à la fin de votre programme ou peut traiter la partie suivante du programme comme une chaîne jusqu'à la prochaine chaîne. Dans le second cas, cela pourrait ne pas produire de message d'erreur du tout! 26 | Un opérateur d'ouverture non fermé - (, {, ou [- fait en sorte que Python continue avec la ligne suivante dans le cadre de l'instruction en cours. Généralement, une erreur se produit presque immédiatement dans la ligne suivante. 27 | Recherchez le classique = au lieu de == dans un conditionnel. 28 | Vérifiez l’indentation pour vous assurer qu’elle s’aligne comme il se doit. Python peut gérer l'espace et les tabulations, mais si vous les mélangez, cela peut poser des problèmes. Le meilleur moyen d'éviter ce problème consiste à utiliser un éditeur de texte connaissant Python et générant une indentation cohérente. 29 | Si vous avez des caractères non-ASCII dans le code (y compris des chaînes et des commentaires), cela peut poser problème, bien que Python 3 gère généralement les caractères non-ASCII. Faites attention si vous collez du texte à partir d'une page Web ou d'une autre source. 30 | Si rien ne fonctionne, passez à la section suivante ... 31 | 32 | A.1.1 Je continue à faire des changements et cela ne fait aucune différence. 33 | Si l'interprète dit qu'il y a une erreur et que vous ne la voyez pas, c'est peut-être parce que l'interprète et vous-même ne regardez pas le même code. Vérifiez votre environnement de programmation pour vous assurer que le programme que vous êtes en train d’éditer est celui que Python essaie d’exécuter. 34 | 35 | Si vous n'êtes pas sûr, essayez de mettre une erreur de syntaxe évidente et délibérée au début du programme. Maintenant, lancez-le à nouveau. Si l'interprète ne trouve pas la nouvelle erreur, vous n'exécutez pas le nouveau code. 36 | 37 | Il y a quelques coupables probables: 38 | 39 | Vous avez modifié le fichier et oublié de sauvegarder les modifications avant de le réexécuter. Certains environnements de programmation le font pour vous, mais pas tous. 40 | Vous avez modifié le nom du fichier, mais vous utilisez toujours l'ancien nom. 41 | Quelque chose dans votre environnement de développement est configuré de manière incorrecte. 42 | Si vous écrivez un module et utilisez import, assurez-vous de ne pas attribuer à votre module le même nom que l’un des modules Python standard. 43 | Si vous utilisez import pour lire un module, rappelez-vous que vous devez redémarrer l'interpréteur ou utiliser reload pour lire un fichier modifié. Si vous importez à nouveau le module, il ne fait rien. 44 | Si vous êtes bloqué et que vous ne pouvez pas comprendre ce qui se passe, une approche consiste à recommencer avec un nouveau programme tel que «Hello, World!», Et à vous assurer de pouvoir exécuter un programme connu. Ajoutez ensuite progressivement les éléments du programme original au nouveau. 45 | 46 | A.2 Erreurs d'exécution 47 | Une fois que votre programme est syntaxiquement correct, Python peut le lire et au moins commencer à l'exécuter. Qu'est ce qui pourrait aller mal? 48 | 49 | A.2.1 Mon programme ne fait absolument rien. 50 | Ce problème est plus fréquent lorsque votre fichier est constitué de fonctions et de classes mais n’appelle pas réellement une fonction pour démarrer l’exécution. Cela peut être intentionnel si vous envisagez d'importer ce module uniquement pour fournir des classes et des fonctions. 51 | 52 | Si ce n'est pas intentionnel, assurez-vous qu'il y a un appel de fonction dans le programme et assurez-vous que le flux d'exécution le parvient (voir «Flux d'exécution» ci-dessous). 53 | 54 | A.2.2 Mon programme se bloque. 55 | 56 | Si un programme s’arrête et semble ne rien faire, il est "suspendu". Cela signifie souvent qu'il est pris dans une boucle infinie ou une récursion infinie. 57 | 58 | Si vous pensez que le problème est lié à une boucle en particulier, ajoutez une instruction print immédiatement avant la boucle indiquant «entrer dans la boucle» et une autre immédiatement après indiquant «quitter la boucle». 59 | Exécutez le programme. Si vous recevez le premier message et non le second, vous obtenez une boucle infinie. Allez à la section «Boucle infinie» ci-dessous. 60 | 61 | La plupart du temps, une récursion infinie entraîne l'exécution du programme pendant un certain temps, puis une erreur . Si cela se produit, consultez la section «Récursion infinie» ci-dessous. 62 | Si vous n'obtenez pas cette erreur mais que vous suspectez un problème lié à une méthode ou à une fonction récursive, vous pouvez toujours utiliser les techniques décrites dans la section «Récursion infinie». 63 | 64 | Si aucune de ces étapes ne fonctionne, commencez à tester d'autres boucles et d'autres fonctions et méthodes récursives. 65 | Si cela ne fonctionne pas, il est possible que vous ne compreniez pas le déroulement de l’exécution dans votre programme. Allez à la section «Flux d’exécution» ci-dessous. 66 | 67 | Boucle infinie 68 | 69 | Si vous pensez avoir une boucle infinie et que vous savez quelle boucle est la cause du problème, ajoutez une instruction print à la fin de la boucle, qui affiche les valeurs des variables de la condition et la valeur de la condition. 70 | 71 | Par exemple: 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Maintenant, lorsque vous exécutez le programme, vous verrez trois lignes de sortie pour chaque passage dans la boucle. La dernière fois dans la boucle, la condition devrait être False. Si la boucle continue, vous pourrez voir les valeurs de x et y et vous pourrez comprendre pourquoi elles ne sont pas mises à jour correctement. 81 | 82 | Récursion infinie 83 | 84 | La plupart du temps, une récursion infinie entraîne l'exécution du programme pendant un certain temps, puis une erreur de dépassement de la profondeur de récursivité maximale. 85 | 86 | Si vous pensez qu'une fonction provoque une récursion infinie, assurez-vous qu'il existe un cas de base. Il devrait y avoir une condition qui provoque le retour de la fonction sans faire une invocation récursive. Sinon, vous devez repenser l'algorithme et identifier un cas de base. 87 | 88 | S'il existe un scénario de base mais que le programme ne semble pas l'atteindre, ajoutez une instruction print au début de la fonction permettant d'imprimer les paramètres. Maintenant, lorsque vous exécuterez le programme, vous verrez quelques lignes de sortie à chaque fois que la fonction est appelée et vous verrez les valeurs des paramètres. Si les paramètres ne se déplacent pas vers le scénario de base, vous obtiendrez des idées sur les raisons pour lesquelles elle fonctionne pas. 89 | 90 | Flux d'exécution 91 | 92 | Si vous ne savez pas comment le flux d'exécution se déplace dans votre programme, ajoutez des instructions print au début de chaque fonction avec un message du type «saisie de la fonction foo», où foo est le nom de la fonction. 93 | 94 | Maintenant, lorsque vous exécutez le programme, il imprimera une trace de chaque fonction à mesure qu’elle est appelée. 95 | 96 | A.2.3 Lorsque je lance le programme, je reçois une exception. 97 | 98 | En cas de problème au cours de l'exécution, Python imprime un message contenant le nom de l'exception, la ligne du programme où le problème s'est produit et une trace. 99 | 100 | Le suivi identifie la fonction en cours d'exécution, puis la fonction qui l'a appelée, puis la fonction qui l'a appelée, etc. En d'autres termes, il retrace la séquence des appels de fonction qui vous ont amené à l'endroit où vous vous trouvez, y compris le numéro de ligne de votre fichier où chaque appel a eu lieu. 101 | 102 | La première étape consiste à examiner le lieu dans lequel l'erreur s'est produite dans le programme et à voir si vous pouvez comprendre ce qui s'est passé. Voici quelques-unes des erreurs d'exécution les plus courantes: 103 | 104 | NameError: 105 | Vous essayez d’utiliser une variable qui n’existe pas dans l’environnement actuel. Vérifiez si le nom est orthographié correctement, ou au moins de manière cohérente. Et rappelez-vous que les variables locales sont locales; vous ne pouvez pas vous y référer de l'extérieur de la fonction où ils sont définis. 106 | TypeError: 107 | Il y a plusieurs causes possibles: 108 | Vous essayez d'utiliser une valeur de manière incorrecte. Exemple: indexer une chaîne, une liste ou un tuple avec autre chose qu'un entier. 109 | Il y a une discordance entre les éléments d'une chaîne de format et les éléments passés à la conversion. Cela peut se produire si le nombre d'éléments ne correspond pas ou si une conversion non valide est appelée. 110 | Vous transmettez un nombre incorrect d'arguments à une fonction. Pour les méthodes, regardez la définition de la méthode et vérifiez que le premier paramètre est self. Ensuite, regardez l'invocation de la méthode. assurez-vous d'appeler la méthode sur un objet avec le bon type et de fournir les autres arguments correctement. 111 | KeyError: 112 | Vous essayez d'accéder à un élément d'un dictionnaire à l'aide d'une clé qu'il ne contient pas. Si les clés sont des chaînes, rappelez-vous que la capitalisation est importante. 113 | AttributeError: 114 | Vous essayez d'accéder à un attribut ou à une méthode qui n'existe pas. Vérifier l'orthographe! Vous pouvez utiliser les vars de fonction intégrés pour répertorier les attributs existants. 115 | Si un AttributeError indique qu'un objet a NoneType, cela signifie qu'il est None. Le problème n'est donc pas le nom de l'attribut, mais l'objet. 116 | 117 | La raison pour laquelle l'objet est nul peut être que vous avez oublié de renvoyer une valeur à partir d'une fonction; si vous arrivez à la fin d'une fonction sans frapper une instruction return, elle ne renvoie aucun. Une autre cause courante consiste à utiliser le résultat d'une méthode de liste, telle que sort, qui renvoie Aucun. 118 | 119 | IndexError: 120 | L'index que vous utilisez pour accéder à une liste, une chaîne ou un tuple est supérieur à sa longueur moins un. Immédiatement avant le site de l'erreur, ajoutez une instruction print pour afficher la valeur de l'index et la longueur du tableau. Le tableau est-il à la bonne taille? Est-ce que l'indice est la bonne valeur? 121 | Le débogueur Python (pdb) est utile pour détecter les exceptions, car il vous permet d'examiner l'état du programme immédiatement avant l'erreur. Vous pouvez en savoir plus sur pdb à l’adresse https://docs.python.org/3/library/pdb.html. 122 | 123 | A.2.4 J'ai ajouté tellement d'instructions print que je suis inondé de résultats. 124 | 125 | L'un des problèmes liés à l'utilisation des instructions print pour le débogage est que vous pouvez vous retrouver enterré dans la sortie. Il y a deux façons de procéder: simplifier la sortie ou simplifier le programme. 126 | 127 | Pour simplifier la sortie, vous pouvez supprimer ou commenter les instructions d’impression qui ne vous aident pas, les combiner ou formater la sortie pour la rendre plus facile à comprendre. 128 | 129 | Pour simplifier le programme, vous pouvez faire plusieurs choses. Premièrement, réduisez le problème sur lequel le programme travaille. Par exemple, si vous recherchez une liste, cherchez une petite liste. Si le programme reçoit une entrée de l'utilisateur, donnez-lui l'entrée la plus simple qui cause le problème. 130 | 131 | Deuxièmement, nettoyez le programme. Supprimez le code mort et réorganisez le programme pour le rendre aussi facile à lire que possible. Par exemple, si vous soupçonnez que le problème se trouve dans une partie profondément imbriquée du programme, essayez de réécrire cette partie avec une structure plus simple. Si vous soupçonnez une grande fonction, essayez de la diviser en petites fonctions et de les tester séparément. 132 | 133 | Souvent, le processus de recherche du scénario de test minimal vous conduit au bogue. Si vous trouvez qu'un programme fonctionne dans une situation mais pas dans une autre, cela vous donne un indice sur ce qui se passe. 134 | 135 | De même, la réécriture d'un morceau de code peut vous aider à trouver des bogues subtils. Si vous apportez un changement qui, à votre avis, ne devrait pas affecter le programme, cela peut vous tromper. 136 | 137 | A.3 Erreurs sémantiques 138 | D'une certaine manière, les erreurs sémantiques sont les plus difficiles à déboguer, car l'interpréteur ne fournit aucune information sur ce qui ne va pas. Seulement vous savez ce que le programme est censé faire. 139 | 140 | La première étape consiste à établir une connexion entre le texte du programme et le comportement observé. Vous avez besoin d'une hypothèse sur ce que fait réellement le programme. Ce qui rend les choses plus difficiles, c’est que les ordinateurs fonctionnent très vite. 141 | 142 | Vous souhaiterez souvent que vous puissiez ralentir le programme à une vitesse humaine et avec certains débogueurs. Mais le temps nécessaire pour insérer quelques instructions print bien placées est souvent court comparé à la configuration du débogueur, à l'insertion et à la suppression de points d'arrêt et à la "progression" du programme jusqu'à l'endroit où l'erreur se produit. 143 | 144 | A.3.1 Mon programme ne fonctionne pas. 145 | Vous devriez vous poser ces questions: 146 | 147 | Y at-il quelque chose que le programme était censé faire mais qui ne semble pas se produire? Recherchez la section du code qui remplit cette fonction et assurez-vous qu'elle s'exécute quand vous le pensez bien. 148 | Est-ce qu'il se passe quelque chose qui ne devrait pas? Trouvez du code dans votre programme qui remplit cette fonction et voyez s’il s’exécute alors que ce n’est pas le cas. 149 | Une section de code produisant un effet qui ne correspond pas à vos attentes? Assurez-vous de bien comprendre le code en question, surtout s'il implique des fonctions ou des méthodes dans d'autres modules Python. Lisez la documentation des fonctions que vous appelez. Essayez-les en écrivant des cas de test simples et en vérifiant les résultats. 150 | Pour programmer, vous avez besoin d'un modèle mental du fonctionnement des programmes. Si vous écrivez un programme qui ne fait pas ce que vous attendez, souvent, le problème ne réside pas dans le programme; c’est dans votre modèle mental. 151 | 152 | La meilleure façon de corriger votre modèle mental est de diviser le programme en ses composants (généralement les fonctions et les méthodes) et de tester chaque composant de manière indépendante. Une fois que vous trouvez la divergence entre votre modèle et la réalité, vous pouvez résoudre le problème. 153 | 154 | Bien sûr, vous devriez créer et tester des composants au fur et à mesure que vous développez le programme. Si vous rencontrez un problème, il ne devrait y avoir qu'une petite quantité de nouveau code dont on ignore qu'elle est correcte. 155 | 156 | A.3.2 J’ai une grande expression poilue et il ne fait pas ce que j’attends. 157 | 158 | L'écriture d'expressions complexes est acceptable tant qu'elles sont lisibles, mais elles peuvent être difficiles à déboguer. Il est souvent judicieux de décomposer une expression complexe en une série d'assignations à des variables temporaires. 159 | 160 | Par exemple: 161 | 162 | 163 | Cela peut être réécrit comme: 164 | 165 | 166 | 167 | 168 | La version explicite est plus facile à lire car les noms de variables fournissent une documentation supplémentaire et il est plus facile de déboguer car vous pouvez vérifier les types des variables intermédiaires et afficher leurs valeurs. 169 | 170 | Un autre problème pouvant survenir avec les grandes expressions est que l'ordre d'évaluation peut ne pas correspondre à vos attentes. Par exemple, si vous traduisez l'expression x / 2 π en Python, vous pouvez écrire: 171 | 172 | y = x / 2 * math.pi 173 | Ce n'est pas correct car la multiplication et la division ont la même priorité et sont évaluées de gauche à droite. Donc, cette expression calcule x π / 2. 174 | 175 | Un bon moyen de déboguer des expressions consiste à ajouter des parenthèses pour rendre explicite l'ordre d'évaluation: 176 | 177 | y = x / (2 * math.pi) 178 | Lorsque vous n'êtes pas sûr de l'ordre d'évaluation, utilisez des parenthèses. Non seulement le programme sera-t-il correct (en ce sens que vous ferez ce que vous vouliez), il sera également plus lisible pour les autres personnes qui n’ont pas mémorisé l’ordre des opérations. 179 | 180 | A.3.3 J'ai une fonction qui ne retourne pas ce que j'attends. 181 | 182 | Si vous avez une instruction return avec une expression complexe, vous ne pouvez pas imprimer le résultat avant de renvoyer. Encore une fois, vous pouvez utiliser une variable temporaire. Par exemple, au lieu de: 183 | 184 | 185 | tu pourrais écrire: 186 | 187 | 188 | 189 | Vous avez maintenant la possibilité d’afficher la valeur de count avant de revenir. 190 | 191 | A.3.4 Je suis vraiment coincé et j’ai besoin d’aide. 192 | Tout d’abord, essayez de vous éloigner de l’ordinateur pendant quelques minutes. Les ordinateurs émettent des ondes qui affectent le cerveau, provoquant les symptômes suivants: 193 | 194 | Frustration et rage. 195 | Croyances superstitieuses («l'ordinateur me déteste») et pensée magique («le programme ne fonctionne que lorsque je porte mon chapeau à l'envers»). 196 | Programmation aléatoire de la marche (tentative de programmer en écrivant tous les programmes possibles et en choisissant celui qui fait le bon choix). 197 | Si vous présentez l'un de ces symptômes, levez-vous et allez vous promener. Lorsque vous êtes calme, pensez au programme. Qu'est-ce que ça fait? Quelles sont les causes possibles de ce comportement? Quand était la dernière fois que vous aviez un programme de travail et qu'avez-vous fait ensuite? 198 | 199 | Parfois, il faut juste du temps pour trouver un bogue. Lorsque je ne suis pas à l’ordinateur, je trouve souvent des bugs et laisse mon esprit vagabonder. Certains des meilleurs endroits pour trouver des bugs sont les trains, les douches et au lit, juste avant de vous endormir. 200 | 201 | A.3.5 Non, j'ai vraiment besoin d'aide. 202 | Ça arrive. Même les meilleurs programmeurs sont parfois bloqués. Parfois, vous travaillez sur un programme si longtemps que vous ne pouvez pas voir l’erreur. Vous avez besoin d'une nouvelle paire d'yeux. 203 | 204 | Avant de faire venir quelqu'un d'autre, assurez-vous d'être prêt. Votre programme doit être aussi simple que possible et vous devez travailler sur la plus petite entrée à l'origine de l'erreur. Vous devez avoir des déclarations imprimées aux endroits appropriés (et le résultat qu'elles produisent doit être compréhensible). Vous devez bien comprendre le problème pour le décrire de manière concise. 205 | 206 | Lorsque vous faites venir quelqu'un pour l'aider, assurez-vous de lui donner les informations dont il a besoin: 207 | 208 | S'il y a un message d'erreur, de quoi s'agit-il et quelle partie du programme indique-t-il? 209 | Quelle était la dernière chose que vous avez faite avant cette erreur? Quelles sont les dernières lignes de code que vous avez écrites ou quel est le nouveau cas de test qui échoue? 210 | Qu'avez-vous essayé jusqu'à présent et qu'avez-vous appris? 211 | Lorsque vous trouvez le bogue, prenez une seconde pour réfléchir à ce que vous auriez pu faire pour le trouver plus rapidement. La prochaine fois que vous verrez quelque chose de similaire, vous pourrez trouver le bogue plus rapidement. 212 | 213 | N'oubliez pas que l'objectif n'est pas simplement de faire en sorte que le programme fonctionne. L’objectif est d’apprendre à faire fonctionner le programme. -------------------------------------------------------------------------------- /chapter03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/chapter03.pdf -------------------------------------------------------------------------------- /chapter04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/chapter04.pdf -------------------------------------------------------------------------------- /chapter05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/chapter05.pdf -------------------------------------------------------------------------------- /chapter06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/chapter06.pdf -------------------------------------------------------------------------------- /chapter07.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 11 | 12 | 13 |
14 | 15 |

Chapitre 7

16 |

Itération

17 |



18 | Ce chapitre concerne l’itération, qui permet d’exécuter un bloc d’instructions à plusieurs reprises. 19 | Nous avons vu une sorte d’itération, en utilisant la récursivité, dans la section 5.8. Nous avons aussi vu un autre type, en utilisant un 20 | boucle for, dans la section 4.2. Dans ce chapitre, nous verrons un autre type, en utilisant une instruction while. 21 | Mais je veux d’abord en dire un peu plus sur l’affectation de variables.

22 |

7.1 Réaffectation

23 |

Comme vous avez pu le constater, il est légal de confier plusieurs affectations à la même 24 | variable. Une nouvelle affectation fait qu’une variable existante se réfère à une nouvelle valeur (et arrête 25 | de faire référence à l’ancienne valeur).

26 |
>>> x = 5
 27 | >>> x
 28 | 5
 29 | >>> x = 7
 30 | >>> x
 31 | 7
 32 | 
33 | 34 |

La première fois que nous affichons x, sa valeur est 5; la deuxième fois, sa valeur est 7.

35 |

Le dessin 7.1 montre à quoi ressemble la réaffectation dans un diagramme d’état.

36 |

À ce stade, je veux aborder une source commune de confusion. Parce que Python utilise le 37 | signe égal (=) pour l’affectation, il est tentant d’interpréter un énoncé comme a = b comme une proposition mathématique d’égalité; c’est-à-dire que a et b sont égaux. Mais cette interprétation est fausse. 38 | Tout d’abord, l’égalité est une relation symétrique et l’affectation ne l’est pas. Par exemple, en mathématiques, si a = 7 alors 7 = a. Mais en Python, l’instruction a = 7 est légale de 7 = a 39 | est faux. 40 | De plus, en mathématiques, une proposition d’égalité est vraie ou faux pour tous les temps. Si a = 41 | b maintenant, alors b sera toujours égal à a. En Python, une instruction d’affectation peut faire deux 42 | variables égales, mais ils ne doivent pas rester comme ça:

43 |
>>> a = 5
 44 | >>> b = a    # a and b are now equal
 45 | >>> a = 3    # a and b are no longer equal
 46 | >>> b
 47 | 5
 48 | 
49 | 50 |

La troisième ligne change la valeur de a mais ne change pas la valeur de b, donc elles ne sont pas 51 | plus égal 52 | La réaffectation des variables est souvent utile, mais vous devez l’utiliser avec prudence. Si les valeurs des 53 | variables changent fréquemment, cela peut rendre le code difficile à lire et à déboguer.

54 |

fig7.1

55 |

Figure 7.1: Diagramme d’état.

56 |

7.2 Mise à jour des variables

57 |

Un type courant de réaffectation est une mise à jour, où la nouvelle valeur de la variable dépend 58 | sur l’ancien

59 |
>>> x = x + 1
 60 | 
61 | 62 |

Cela signifie “obtenir la valeur actuelle de x, ajouter un, puis mettre à jour x avec la nouvelle valeur.” 63 | Si vous essayez de mettre à jour une variable qui n’existe pas, vous obtenez une erreur, car Python évalue 64 | le côté droit avant d’assigner une valeur à x:

65 |
>>> x = x + 1
 66 | NameError: name 'x' is not defined
 67 | 
68 | 69 |

Avant de pouvoir mettre à jour une variable, vous devez l’initialiser, généralement avec une affectation simple:

70 |
>>> x = 0
 71 | >>> x = x + 1
 72 | 
73 | 74 |

La mise à jour d’une variable en ajoutant 1 est appelée un incrément; soustraire 1 est appelé décrément.

75 |

7.3 La boucle while

76 |

Les ordinateurs sont souvent utilisés pour automatiser des tâches répétitives. Répéter des tâches identiques ou similaires 77 | sans faire d’erreurs est quelque chose que les ordinateurs font bien et que les gens font mal. Dans un 78 | programme informatique, la répétition est aussi appelée itération. 79 | Nous avons déjà vu deux fonctions, countdown et print_n, qui itèrent en utilisant la récursivité. 80 | Comme l’itération est si courante, Python fournit des fonctionnalités de langage pour le rendre plus facile. Un 81 | est la déclaration for que nous avons vue à la section 4.2. Nous y reviendrons plus tard. 82 | Une autre est la boucle while. Voici une version du compte à rebours qui utilise une instruction while:

83 |
def countdown(n):
 84 |     while n > 0:
 85 |         print(n)
 86 |         n = n - 1
 87 |     print('Blastoff!')
 88 | 
89 | 90 |

Vous pouvez presque lire la déclaration while comme si c’était l’anglais. Cela signifie que “Alors que n est plus grand 91 | que 0, affiche la valeur de n puis décrémente n. Lorsque vous arrivez à 0, affichez le mot 92 | blastoff”

93 |

Plus formellement, voici le déroulement de l’exécution: 94 | 1. Déterminez si la condition est vraie ou fausse. 95 | 2. Si la valeur est false, quittez l’instruction while et continuez l’exécution à l’instruction suivante. 96 | 3. Si la condition est vraie, lancez le corps et retournez à l’étape 1.

97 |

Ce type de flux est appelé une boucle car la troisième étape est bouclée vers le haut. 98 | Le corps de la boucle devrait changer la valeur d’une ou plusieurs variables pour que la condition 99 | devient finalement faux et la boucle se termine. Sinon, la boucle se répètera pour toujours, 100 | qui s’appelle une boucle infinie. Une source d’amusement sans fin pour les informaticiens 101 | est l’observation que les instructions sur le shampooing, “Lather, rinse, repeat”, est une boucle 102 | infinie. 103 | Dans le cas du compte à rebours, on peut prouver que la boucle se termine: si n est zéro ou négatif, le 104 | boucle ne fonctionne jamais. Sinon, n diminue chaque fois à travers la boucle, donc finalement nous 105 | doivent arriver à 0. 106 | Pour d’autres boucles, ce n’est pas si facile à dire. Par exemple:

107 |
def sequence(n):
108 |     while n != 1:
109 |         print(n)
110 |         if n % 2 == 0:        # n is even
111 |             n = n / 2
112 |         else:                 # n is odd
113 |             n = n * 3 + 1
114 | 
115 | 116 |

La condition pour cette boucle est n! = 1, donc la boucle continuera jusqu’à ce que n soit 1, ce qui rend 117 | la condition fausse. 118 | À chaque fois dans la boucle, le programme affiche la valeur de n et vérifie ensuite si 119 | c’est pair ou impair. Si c’est pair, n est divisé par 2. S’il est impair, la valeur de n est remplacée par 120 | n * 3 + 1. Par exemple, si l’argument passé à la séquence est 3, les valeurs résultantes de n 121 | sont 3, 10, 5, 16, 8, 4, 2, 1. 122 | Comme n augmente et diminue parfois, il n’ya pas de preuve évidente que n 123 | atteindra 1, ou que le programme se termine. Pour certaines valeurs particulières de n, nous pouvons prouver 124 | la términaison. Par exemple, si la valeur de départ est une puissance de deux, n sera pair à 125 | chaque fois dans la boucle jusqu’à ce qu’il atteigne 1. L’exemple précédent se termine par une telle séquence, 126 | à partir de 16. 127 | La question difficile est de savoir si nous pouvons prouver que ce programme se termine pour toutes les valeurs positives de n. Jusqu’à présent, personne n’a été capable de le prouver ou de le réfuter! Voyez collatz conjecture)

128 |

En guise d’exercice, réécrivez la fonction print_n de la section 5.8 en utilisant l’itération au lieu de 129 | récursivité.

130 |

7.4 Break

131 |

Parfois, vous ne savez pas qu’il est temps de terminer une boucle jusqu’à ce que vous atteigniez la moitié du corps. 132 | Dans ce cas, vous pouvez utiliser l’instruction break pour sortir de la boucle. 133 | Par exemple, supposons que vous souhaitiez saisir les informations de l’utilisateur jusqu’à ce qu’elles soient saisies. Vous pourriez 134 | écrire:

135 |
while True:
136 |     line = input('> ')
137 |     if line == 'done':
138 |         break
139 |     print(line)
140 | 
141 | print('Done!')
142 | 
143 | 144 |

La condition de la boucle est True, ce qui est toujours vrai, donc la boucle s’exécute jusqu’à ce qu’elle atteigne la déclaration de 145 | rupture. 146 | À chaque fois, l’utilisateur est invité à choisir une option. Si l’utilisateur type ‘done’ (terminé), l’ 147 | instruction break quitte la boucle. Sinon, le programme reimprime ce que l’utilisateur type et 148 | retourne au sommet de la boucle. Voici un exemple:

149 |
> not done
150 | not done
151 | > done
152 | Done!
153 | 
154 | 155 |

Cette façon d’écrire des boucles est commune car vous pouvez vérifier la condition n’importe où 156 | dans la boucle (pas seulement en haut) et vous pouvez exprimer la condition d’arrêt de manière affirmative (“arretez 157 | quand cela se produit “) plutôt que négativement (” continuez jusqu’à ce que cela arrive “).

158 |

7.5 Racines carrées

159 |

Les boucles sont souvent utilisées dans les programmes qui calculent des résultats numériques en commençant par une réponse approximative et en l’améliorant de manière itérative. 160 | Par exemple, une méthode de calcul des racines carrées est la méthode de Newton. Supposons que vous 161 | voulez savoir la racine carrée de a. Si vous commencez avec presque n’importe quelle estimation, x, vous pouvez calculer une meilleure estimation avec la formule suivante:

162 |
y = (x + a/x) / 2
163 | 
164 | 165 |

Par exemple, si a est 4 et que x est 3:

166 |
>>> a = 4
167 | >>> x = 3
168 | >>> y = (x + a / x) / 2
169 | >>> y
170 | 2.16666666667
171 | 
172 | 173 |

Le résultat est plus proche de la réponse correcte (4 = 2). Si nous répétons le processus avec le nouveau 174 | estimation, il devient encore plus proche:

175 |
>>> x = y
176 | >>> y = (x + a / x) / 2
177 | >>> y
178 | 2.00641025641
179 | 
180 | 181 |

Après quelques mises à jour supplémentaires, l’estimation est presque exacte:

182 |
>>> x = y
183 | >>> y = (x + a / x) / 2
184 | >>> y
185 | 2.00001024003
186 | >>> x = y
187 | >>> y = (x + a / x) / 2
188 | >>> y
189 | 2.00000000003
190 | 
191 | 192 |

En général, nous ne savons pas combien de temps il faut pour arriver à la bonne réponse, 193 | mais on sait quand on arrive là-bas car le devis cesse de changer:

194 |
>>> x = y
195 | >>> y = (x + a / x) / 2
196 | >>> y
197 | 2.0
198 | >>> x = y
199 | >>> y = (x + a / x) / 2
200 | >>> y
201 | 2.0
202 | 
203 | 204 |

Lorsque y == x, on peut s’arrêter. Voici une boucle qui commence par une estimation initiale, x, et l’améliore jusqu’à ce qu’elle cesse de changer:

205 |
while True:
206 |     print(x)
207 |     y = (x + a/x) / 2
208 |     if y == x:
209 |         break
210 |     x = y
211 | 
212 | 213 |

Pour la plupart des valeurs de a, cela fonctionne bien, mais en général, il est dangereux de tester l’égalité des flottants. 214 | Les valeurs à virgule flottante sont approximativement correctes: la plupart des nombres rationnels, comme 1/3, et 215 | les nombres irrationnels, comme 2, ne peuvent pas être représentés exactement avec un flottant. 216 | Plutôt que de vérifier si x et y sont exactement égaux, il est préférable d’utiliser la fonction intégrée abs pour calculer la valeur absolue, ou l’ampleur, de la différence entre eux:

217 |

if abs(y-x) < epsilon: 218 | break 219 | Où epsilon a une valeur comme 0.0000001 qui détermine la proximité est assez proche.

220 |

7.6 Algorithmes

221 |

La méthode de Newton est un exemple d’algorithme: c’est un processus mécanique pour résoudre un 222 | catégorie de problèmes (dans ce cas, calcul des racines carrées).n

223 |

Pour comprendre ce qu’est un algorithme, il peut être utile de commencer par quelque chose qui n’est pas un 224 | algorithme. Lorsque vous avez appris à multiplier des nombres à un chiffre, vous avez probablement mémorisé 225 | la table de multiplication. En effet, vous avez mémorisé 100 solutions spécifiques. Ce genre de 226 | connaissance n’est pas algorithmique. 227 | Mais si vous étiez “paresseux”, vous avez peut-être appris quelques astuces. Par exemple, pour trouver le 228 | produit de n et 9, vous pouvez écrire n-1 comme premier chiffre et 10-n comme deuxième chiffre. 229 | Cette astuce est une solution générale pour multiplier un nombre à un chiffre par 9. C’est un 230 | algorithme! 231 | De même, les techniques que vous avez apprises pour l’addition avec transport, la soustraction avec emprunt et la division longue sont toutes des algorithmes. L’une des caractéristiques des algorithmes est que 232 | ils n’ont besoin d’aucune intelligence pour effectuer. Ce sont des processus mécaniques où 233 | chaque étape découle de la dernière selon un ensemble simple de règles. 234 | L’exécution d’algorithmes est ennuyeuse, mais leur conception est intéressante, un défi intellectuel et constitue un élément central de l’informatique. 235 | Certaines des choses que les gens font naturellement, sans difficulté, ni pensée consciente, sont: 236 | le plus difficile à exprimer algorithmiquement. Comprendre le langage naturel est un bon exemple. 237 | Nous le faisons tous, mais jusqu’à présent, personne n’a pu expliquer comment nous le faisons, du moins pas sous la forme 238 | d’un algorithme.

239 |

7.7 Le débogage

240 |

Lorsque vous commencez à écrire de plus gros programmes, vous risquez de devoir passer plus de temps à déboguer. Plus de code signifie plus de chances de faire une erreur et plus d’endroits où les bogues peuvent se cacher. 241 | Un moyen de réduire votre temps de débogage est le “débogage par bissection”. Par exemple, s’il y a 242 | sont 100 lignes dans votre programme et vous les vérifiez un par un, cela prendrait 100 étapes. 243 | Au lieu de cela, essayez de briser le problème en deux. Regardez au milieu du programme, ou à proximité, pour 244 | une valeur intermédiaire que vous pouvez vérifier. Ajouter un relevé d’impression (ou autre chose qui a un 245 | effet vérifiable) et exécuter le programme. 246 | Si la vérification à mi-parcours est incorrecte, il doit y avoir un problème dans la première moitié du programme. 247 | Si c’est correct, le problème est dans la seconde moitié. 248 | Chaque fois que vous effectuez une vérification comme celle-ci, vous divisez par deux le nombre de lignes à rechercher. 249 | Après six étapes (moins de 100), vous seriez réduit à une ou deux lignes de code, 250 | au moins en théorie. 251 | En pratique, il n’est pas toujours évident de savoir ce que le “milieu du programme” est et n’est pas toujours possible de vérifier. Cela n’a aucun sens de compter les lignes et de trouver le point médian exact. Au lieu, 252 | penser à des endroits du programme où il peut y avoir des erreurs et des endroits faciles à 253 | mettre un checkpoint. Ensuite, choisissez un endroit où vous pensez que les chances sont à peu près les mêmes 254 | le bug est avant ou après la vérification.

255 |

7.8 Glossaire

256 |
    257 |
  • 258 |

    réaffectation: attribuer une nouvelle valeur à une variable qui existe déjà.

    259 |
  • 260 |
  • 261 |

    update: Affectation où la nouvelle valeur de la variable dépend de l’ancienne.

    262 |
  • 263 |
  • 264 |

    initialization: une affectation qui donne une valeur initiale à une variable qui sera mise à jour.

    265 |
  • 266 |
  • 267 |

    increment: une mise à jour qui augmente la valeur d’une variable (souvent par une seule).

    268 |
  • 269 |
  • 270 |

    décrément: une mise à jour qui diminue la valeur d’une variable.

    271 |
  • 272 |
  • 273 |

    iteration: exécution répétée d’un ensemble d’instructions à l’aide d’un appel de fonction récursif 274 | ou une boucle.

    275 |
  • 276 |
  • 277 |

    boucle infinie: boucle dans laquelle la condition de terminaison n’est jamais satisfaite.

    278 |
  • 279 |
  • 280 |

    algorithme: un processus général pour résoudre une catégorie de problèmes.

    281 |
  • 282 |
283 |

7.9 Des exercices

284 |

Exercice 1

285 |

Copiez la boucle de la section 7.5 et encapsulez-la dans une fonction appelée mysqrt 286 | prend un comme paramètre, choisit une valeur raisonnable de x et renvoie une estimation de la racine carrée de 287 | une. 288 | Pour le tester, écrivez une fonction nommée test_square_root qui imprime un tableau comme celui-ci:

289 |
a   mysqrt(a)     math.sqrt(a)  diff
290 | -   ---------     ------------  ----
291 | 1.0 1.0           1.0           0.0
292 | 2.0 1.41421356237 1.41421356237 2.22044604925e-16
293 | 3.0 1.73205080757 1.73205080757 0.0
294 | 4.0 2.0           2.0           0.0
295 | 5.0 2.2360679775  2.2360679775  0.0
296 | 6.0 2.44948974278 2.44948974278 0.0
297 | 7.0 2.64575131106 2.64575131106 0.0
298 | 8.0 2.82842712475 2.82842712475 4.4408920985e-16
299 | 9.0 3.0           3.0           0.0
300 | 
301 | 302 |

La première colonne est un nombre, a; la deuxième colonne est la racine carrée d’un calcul avec mysqrt; 303 | la troisième colonne est la racine carrée calculée par math.sqrt; la quatrième colonne est la valeur absolue 304 | de la différence entre les deux estimations.

305 |

Exercice 2

306 |

La fonction intégrée eval prend une chaîne et l’évalue à l’aide de l’interpréteur Python. Par exemple:

307 |
>>> eval('1 + 2 * 3')
308 | 7
309 | >>> import math
310 | >>> eval('math.sqrt(5)')
311 | 2.2360679774997898
312 | >>> eval('type(math.pi)')
313 | <class 'float'>
314 | 
315 | 316 |

Ecrire une fonction appelée eval_loop qui invite de manière itérative l’utilisateur, prend l’entrée résultante et 317 | l’évalue en utilisant eval et imprime le résultat. 318 | Il doit continuer jusqu’à ce que l’utilisateur entre “done”, puis renvoyer la valeur de la dernière expression 319 | évalué.

320 |

Exercice 7.3.

321 |

Le mathématicien Srinivasa Ramanujan a trouvé une série infinie qui peut être utilisée pour 322 | générer une approximation numérique de 1 / π:

323 |
                  ∞
324 | 1/π = 2√2 / 9801  ∑   (4k)!(1103+26390k) / (k!)4 3964k
325 |                  k=0  
326 | 
327 | 328 |

Ecrivez une fonction appelée estimation_pi qui utilise cette formule pour calculer et renvoyer une estimation de 329 | π. Il devrait utiliser une boucle while pour calculer les termes de la sommation jusqu’à ce que le dernier terme soit plus petit que 330 | 1e-15 (qui est la notation Python pour 10-15). Vous pouvez vérifier le résultat en le comparant à math.pi. 331 | Solution: http://thinkpython2.com/code/pi.py

332 | 333 | 334 | 335 |
336 | 337 | -------------------------------------------------------------------------------- /chapter07.md: -------------------------------------------------------------------------------- 1 | # Chapitre 7 2 | 3 | ## Itération 4 |

5 | Ce chapitre concerne l'itération, qui permet d'exécuter un bloc d'instructions à plusieurs reprises. 6 | Nous avons vu une sorte d'itération, en utilisant la récursivité, dans la section 5.8. Nous avons aussi vu un autre type, en utilisant un 7 | boucle for, dans la section 4.2. Dans ce chapitre, nous verrons un autre type, en utilisant une instruction while. 8 | Mais je veux d'abord en dire un peu plus sur l'affectation de variables. 9 | 10 | ## 7.1 Réaffectation 11 | 12 | Comme vous avez pu le constater, il est légal de confier plusieurs affectations à la même 13 | variable. Une nouvelle affectation fait qu'une variable existante se réfère à une nouvelle valeur (et arrête 14 | de faire référence à l'ancienne valeur). 15 | 16 | ```python 17 | >>> x = 5 18 | >>> x 19 | 5 20 | >>> x = 7 21 | >>> x 22 | 7 23 | ``` 24 | 25 | La première fois que nous affichons x, sa valeur est 5; la deuxième fois, sa valeur est 7. 26 | 27 | Le dessin 7.1 montre à quoi ressemble la réaffectation dans un diagramme d'état. 28 | 29 | À ce stade, je veux aborder une source commune de confusion. Parce que Python utilise le 30 | signe égal (=) pour l'affectation, il est tentant d'interpréter un énoncé comme a = b comme une proposition mathématique d'égalité; c'est-à-dire que a et b sont égaux. Mais cette interprétation est fausse. 31 | Tout d'abord, l'égalité est une relation symétrique et l'affectation ne l'est pas. Par exemple, en mathématiques, si a = 7 alors 7 = a. Mais en Python, l'instruction a = 7 est légale de 7 = a 32 | est faux. 33 | De plus, en mathématiques, une proposition d’égalité est vraie ou faux pour tous les temps. Si a = 34 | b maintenant, alors b sera toujours égal à a. En Python, une instruction d'affectation peut faire deux 35 | variables égales, mais ils ne doivent pas rester comme ça: 36 | 37 | 38 | 39 | ```python 40 | >>> a = 5 41 | >>> b = a # a and b are now equal 42 | >>> a = 3 # a and b are no longer equal 43 | >>> b 44 | 5 45 | ``` 46 | 47 | 48 | La troisième ligne change la valeur de a mais ne change pas la valeur de b, donc elles ne sont pas 49 | plus égal 50 | La réaffectation des variables est souvent utile, mais vous devez l'utiliser avec prudence. Si les valeurs des 51 | variables changent fréquemment, cela peut rendre le code difficile à lire et à déboguer. 52 | 53 | ![fig7.1](assets/tp7.1.png) 54 | 55 | Figure 7.1: Diagramme d'état. 56 | 57 | ## 7.2 Mise à jour des variables 58 | 59 | Un type courant de réaffectation est une mise à jour, où la nouvelle valeur de la variable dépend 60 | sur l'ancien 61 | 62 | ```python 63 | >>> x = x + 1 64 | ``` 65 | 66 | Cela signifie "obtenir la valeur actuelle de x, ajouter un, puis mettre à jour x avec la nouvelle valeur." 67 | Si vous essayez de mettre à jour une variable qui n’existe pas, vous obtenez une erreur, car Python évalue 68 | le côté droit avant d'assigner une valeur à x: 69 | 70 | ```python 71 | >>> x = x + 1 72 | NameError: name 'x' is not defined 73 | ``` 74 | 75 | Avant de pouvoir mettre à jour une variable, vous devez l'initialiser, généralement avec une affectation simple: 76 | 77 | ```python 78 | >>> x = 0 79 | >>> x = x + 1 80 | ``` 81 | 82 | La mise à jour d'une variable en ajoutant 1 est appelée un incrément; soustraire 1 est appelé décrément. 83 | 84 | ## 7.3 La boucle while 85 | 86 | Les ordinateurs sont souvent utilisés pour automatiser des tâches répétitives. Répéter des tâches identiques ou similaires 87 | sans faire d'erreurs est quelque chose que les ordinateurs font bien et que les gens font mal. Dans un 88 | programme informatique, la répétition est aussi appelée itération. 89 | Nous avons déjà vu deux fonctions, countdown et print_n, qui itèrent en utilisant la récursivité. 90 | Comme l'itération est si courante, Python fournit des fonctionnalités de langage pour le rendre plus facile. Un 91 | est la déclaration for que nous avons vue à la section 4.2. Nous y reviendrons plus tard. 92 | Une autre est la boucle while. Voici une version du compte à rebours qui utilise une instruction while: 93 | 94 | ```python 95 | def countdown(n): 96 | while n > 0: 97 | print(n) 98 | n = n - 1 99 | print('Blastoff!') 100 | ``` 101 | 102 | Vous pouvez presque lire la déclaration while comme si c'était l'anglais. Cela signifie que "Alors que n est plus grand 103 | que 0, affiche la valeur de n puis décrémente n. Lorsque vous arrivez à 0, affichez le mot 104 | blastoff" 105 | 106 | Plus formellement, voici le déroulement de l’exécution: 107 | 1. Déterminez si la condition est vraie ou fausse. 108 | 2. Si la valeur est false, quittez l'instruction while et continuez l'exécution à l'instruction suivante. 109 | 3. Si la condition est vraie, lancez le corps et retournez à l'étape 1. 110 | 111 | Ce type de flux est appelé une boucle car la troisième étape est bouclée vers le haut. 112 | Le corps de la boucle devrait changer la valeur d'une ou plusieurs variables pour que la condition 113 | devient finalement faux et la boucle se termine. Sinon, la boucle se répètera pour toujours, 114 | qui s'appelle une boucle infinie. Une source d'amusement sans fin pour les informaticiens 115 | est l'observation que les instructions sur le shampooing, "Lather, rinse, repeat", est une boucle 116 | infinie. 117 | Dans le cas du compte à rebours, on peut prouver que la boucle se termine: si n est zéro ou négatif, le 118 | boucle ne fonctionne jamais. Sinon, n diminue chaque fois à travers la boucle, donc finalement nous 119 | doivent arriver à 0. 120 | Pour d'autres boucles, ce n'est pas si facile à dire. Par exemple: 121 | 122 | ```python 123 | def sequence(n): 124 | while n != 1: 125 | print(n) 126 | if n % 2 == 0: # n is even 127 | n = n / 2 128 | else: # n is odd 129 | n = n * 3 + 1 130 | ``` 131 | 132 | La condition pour cette boucle est n! = 1, donc la boucle continuera jusqu'à ce que n soit 1, ce qui rend 133 | la condition fausse. 134 | À chaque fois dans la boucle, le programme affiche la valeur de n et vérifie ensuite si 135 | c'est pair ou impair. Si c'est pair, n est divisé par 2. S'il est impair, la valeur de n est remplacée par 136 | n * 3 + 1. Par exemple, si l'argument passé à la séquence est 3, les valeurs résultantes de n 137 | sont 3, 10, 5, 16, 8, 4, 2, 1. 138 | Comme n augmente et diminue parfois, il n’ya pas de preuve évidente que n 139 | atteindra 1, ou que le programme se termine. Pour certaines valeurs particulières de n, nous pouvons prouver 140 | la términaison. Par exemple, si la valeur de départ est une puissance de deux, n sera pair à 141 | chaque fois dans la boucle jusqu'à ce qu'il atteigne 1. L'exemple précédent se termine par une telle séquence, 142 | à partir de 16. 143 | La question difficile est de savoir si nous pouvons prouver que ce programme se termine pour toutes les valeurs positives de n. Jusqu'à présent, personne n'a été capable de le prouver ou de le réfuter! Voyez [collatz conjecture](http://en.wikipedia.org/wiki/Collatz_conjecture.)) 144 | 145 | En guise d’exercice, réécrivez la fonction print_n de la section 5.8 en utilisant l’itération au lieu de 146 | récursivité. 147 | 148 | ## 7.4 Break 149 | 150 | Parfois, vous ne savez pas qu'il est temps de terminer une boucle jusqu'à ce que vous atteigniez la moitié du corps. 151 | Dans ce cas, vous pouvez utiliser l'instruction break pour sortir de la boucle. 152 | Par exemple, supposons que vous souhaitiez saisir les informations de l'utilisateur jusqu'à ce qu'elles soient saisies. Vous pourriez 153 | écrire: 154 | 155 | ```python 156 | while True: 157 | line = input('> ') 158 | if line == 'done': 159 | break 160 | print(line) 161 | 162 | print('Done!') 163 | ``` 164 | 165 | La condition de la boucle est True, ce qui est toujours vrai, donc la boucle s'exécute jusqu'à ce qu'elle atteigne la déclaration de 166 | rupture. 167 | À chaque fois, l'utilisateur est invité à choisir une option. Si l'utilisateur type 'done' (terminé), l' 168 | instruction break quitte la boucle. Sinon, le programme reimprime ce que l'utilisateur type et 169 | retourne au sommet de la boucle. Voici un exemple: 170 | ``` 171 | > not done 172 | not done 173 | > done 174 | Done! 175 | ``` 176 | Cette façon d'écrire des boucles est commune car vous pouvez vérifier la condition n'importe où 177 | dans la boucle (pas seulement en haut) et vous pouvez exprimer la condition d'arrêt de manière affirmative ("arretez 178 | quand cela se produit ") plutôt que négativement (" continuez jusqu'à ce que cela arrive "). 179 | 180 | ## 7.5 Racines carrées 181 | 182 | Les boucles sont souvent utilisées dans les programmes qui calculent des résultats numériques en commençant par une réponse approximative et en l'améliorant de manière itérative. 183 | Par exemple, une méthode de calcul des racines carrées est la méthode de Newton. Supposons que vous 184 | voulez savoir la racine carrée de a. Si vous commencez avec presque n'importe quelle estimation, x, vous pouvez calculer une meilleure estimation avec la formule suivante: 185 | 186 | ``` 187 | y = (x + a/x) / 2 188 | ``` 189 | 190 | Par exemple, si a est 4 et que x est 3: 191 | 192 | ```python 193 | >>> a = 4 194 | >>> x = 3 195 | >>> y = (x + a / x) / 2 196 | >>> y 197 | 2.16666666667 198 | ``` 199 | 200 | Le résultat est plus proche de la réponse correcte (4 = 2). Si nous répétons le processus avec le nouveau 201 | estimation, il devient encore plus proche: 202 | ```python 203 | >>> x = y 204 | >>> y = (x + a / x) / 2 205 | >>> y 206 | 2.00641025641 207 | ``` 208 | Après quelques mises à jour supplémentaires, l'estimation est presque exacte: 209 | ```python 210 | >>> x = y 211 | >>> y = (x + a / x) / 2 212 | >>> y 213 | 2.00001024003 214 | >>> x = y 215 | >>> y = (x + a / x) / 2 216 | >>> y 217 | 2.00000000003 218 | ``` 219 | En général, nous ne savons pas combien de temps il faut pour arriver à la bonne réponse, 220 | mais on sait quand on arrive là-bas car le devis cesse de changer: 221 | ```python 222 | >>> x = y 223 | >>> y = (x + a / x) / 2 224 | >>> y 225 | 2.0 226 | >>> x = y 227 | >>> y = (x + a / x) / 2 228 | >>> y 229 | 2.0 230 | ``` 231 | Lorsque y == x, on peut s'arrêter. Voici une boucle qui commence par une estimation initiale, x, et l'améliore jusqu'à ce qu'elle cesse de changer: 232 | ```python 233 | while True: 234 | print(x) 235 | y = (x + a/x) / 2 236 | if y == x: 237 | break 238 | x = y 239 | ``` 240 | Pour la plupart des valeurs de a, cela fonctionne bien, mais en général, il est dangereux de tester l'égalité des flottants. 241 | Les valeurs à virgule flottante sont approximativement correctes: la plupart des nombres rationnels, comme 1/3, et 242 | les nombres irrationnels, comme 2, ne peuvent pas être représentés exactement avec un flottant. 243 | Plutôt que de vérifier si x et y sont exactement égaux, il est préférable d'utiliser la fonction intégrée abs pour calculer la valeur absolue, ou l'ampleur, de la différence entre eux: 244 | 245 | if abs(y-x) < epsilon: 246 | break 247 | Où epsilon a une valeur comme 0.0000001 qui détermine la proximité est assez proche. 248 | 249 | ## 7.6 Algorithmes 250 | 251 | La méthode de Newton est un exemple d'algorithme: c'est un processus mécanique pour résoudre un 252 | catégorie de problèmes (dans ce cas, calcul des racines carrées).n 253 | 254 | Pour comprendre ce qu'est un algorithme, il peut être utile de commencer par quelque chose qui n'est pas un 255 | algorithme. Lorsque vous avez appris à multiplier des nombres à un chiffre, vous avez probablement mémorisé 256 | la table de multiplication. En effet, vous avez mémorisé 100 solutions spécifiques. Ce genre de 257 | connaissance n'est pas algorithmique. 258 | Mais si vous étiez "paresseux", vous avez peut-être appris quelques astuces. Par exemple, pour trouver le 259 | produit de n et 9, vous pouvez écrire n-1 comme premier chiffre et 10-n comme deuxième chiffre. 260 | Cette astuce est une solution générale pour multiplier un nombre à un chiffre par 9. C'est un 261 | algorithme! 262 | De même, les techniques que vous avez apprises pour l'addition avec transport, la soustraction avec emprunt et la division longue sont toutes des algorithmes. L'une des caractéristiques des algorithmes est que 263 | ils n'ont besoin d'aucune intelligence pour effectuer. Ce sont des processus mécaniques où 264 | chaque étape découle de la dernière selon un ensemble simple de règles. 265 | L'exécution d'algorithmes est ennuyeuse, mais leur conception est intéressante, un défi intellectuel et constitue un élément central de l'informatique. 266 | Certaines des choses que les gens font naturellement, sans difficulté, ni pensée consciente, sont: 267 | le plus difficile à exprimer algorithmiquement. Comprendre le langage naturel est un bon exemple. 268 | Nous le faisons tous, mais jusqu’à présent, personne n’a pu expliquer comment nous le faisons, du moins pas sous la forme 269 | d'un algorithme. 270 | 271 | ## 7.7 Le débogage 272 | 273 | Lorsque vous commencez à écrire de plus gros programmes, vous risquez de devoir passer plus de temps à déboguer. Plus de code signifie plus de chances de faire une erreur et plus d'endroits où les bogues peuvent se cacher. 274 | Un moyen de réduire votre temps de débogage est le "débogage par bissection". Par exemple, s'il y a 275 | sont 100 lignes dans votre programme et vous les vérifiez un par un, cela prendrait 100 étapes. 276 | Au lieu de cela, essayez de briser le problème en deux. Regardez au milieu du programme, ou à proximité, pour 277 | une valeur intermédiaire que vous pouvez vérifier. Ajouter un relevé d'impression (ou autre chose qui a un 278 | effet vérifiable) et exécuter le programme. 279 | Si la vérification à mi-parcours est incorrecte, il doit y avoir un problème dans la première moitié du programme. 280 | Si c'est correct, le problème est dans la seconde moitié. 281 | Chaque fois que vous effectuez une vérification comme celle-ci, vous divisez par deux le nombre de lignes à rechercher. 282 | Après six étapes (moins de 100), vous seriez réduit à une ou deux lignes de code, 283 | au moins en théorie. 284 | En pratique, il n'est pas toujours évident de savoir ce que le "milieu du programme" est et n'est pas toujours possible de vérifier. Cela n'a aucun sens de compter les lignes et de trouver le point médian exact. Au lieu, 285 | penser à des endroits du programme où il peut y avoir des erreurs et des endroits faciles à 286 | mettre un checkpoint. Ensuite, choisissez un endroit où vous pensez que les chances sont à peu près les mêmes 287 | le bug est avant ou après la vérification. 288 | 289 | ## 7.8 Glossaire 290 | 291 | - **réaffectation:** attribuer une nouvelle valeur à une variable qui existe déjà. 292 | 293 | - **update:** Affectation où la nouvelle valeur de la variable dépend de l'ancienne. 294 | 295 | - **initialization:** une affectation qui donne une valeur initiale à une variable qui sera mise à jour. 296 | 297 | - **increment:** une mise à jour qui augmente la valeur d'une variable (souvent par une seule). 298 | 299 | - **décrément:** une mise à jour qui diminue la valeur d'une variable. 300 | 301 | - **iteration:** exécution répétée d'un ensemble d'instructions à l'aide d'un appel de fonction récursif 302 | ou une boucle. 303 | 304 | - **boucle infinie:** boucle dans laquelle la condition de terminaison n'est jamais satisfaite. 305 | 306 | - **algorithme:** un processus général pour résoudre une catégorie de problèmes. 307 | 308 | ## 7.9 Exercices 309 | 310 | **Exercice 1** 311 | 312 | _Copiez la boucle de la section 7.5 et encapsulez-la dans une fonction appelée mysqrt 313 | prend un comme paramètre, choisit une valeur raisonnable de x et renvoie une estimation de la racine carrée de 314 | une. 315 | Pour le tester, écrivez une fonction nommée test_square_root qui imprime un tableau comme celui-ci:_ 316 | 317 | ``` 318 | a mysqrt(a) math.sqrt(a) diff 319 | - --------- ------------ ---- 320 | 1.0 1.0 1.0 0.0 321 | 2.0 1.41421356237 1.41421356237 2.22044604925e-16 322 | 3.0 1.73205080757 1.73205080757 0.0 323 | 4.0 2.0 2.0 0.0 324 | 5.0 2.2360679775 2.2360679775 0.0 325 | 6.0 2.44948974278 2.44948974278 0.0 326 | 7.0 2.64575131106 2.64575131106 0.0 327 | 8.0 2.82842712475 2.82842712475 4.4408920985e-16 328 | 9.0 3.0 3.0 0.0 329 | ``` 330 | 331 | La première colonne est un nombre, a; la deuxième colonne est la racine carrée d'un calcul avec mysqrt; 332 | la troisième colonne est la racine carrée calculée par math.sqrt; la quatrième colonne est la valeur absolue 333 | de la différence entre les deux estimations. 334 | 335 | **Exercice 2** 336 | 337 | La fonction intégrée eval prend une chaîne et l'évalue à l'aide de l'interpréteur Python. Par exemple: 338 | 339 | ```python 340 | >>> eval('1 + 2 * 3') 341 | 7 342 | >>> import math 343 | >>> eval('math.sqrt(5)') 344 | 2.2360679774997898 345 | >>> eval('type(math.pi)') 346 | 347 | ``` 348 | 349 | Ecrire une fonction appelée eval_loop qui invite de manière itérative l'utilisateur, prend l'entrée résultante et 350 | l'évalue en utilisant eval et imprime le résultat. 351 | Il doit continuer jusqu'à ce que l'utilisateur entre "done", puis renvoyer la valeur de la dernière expression 352 | évalué. 353 | 354 | **Exercice 7.3.** 355 | 356 | Le mathématicien Srinivasa Ramanujan a trouvé une série infinie qui peut être utilisée pour 357 | générer une approximation numérique de 1 / π: 358 | 359 | ``` 360 | ∞ 361 | 1/π = 2√2 / 9801 ∑ (4k)!(1103+26390k) / (k!)4 3964k 362 | k=0 363 | ``` 364 | 365 | Ecrivez une fonction appelée estimation_pi qui utilise cette formule pour calculer et renvoyer une estimation de 366 | π. Il devrait utiliser une boucle while pour calculer les termes de la sommation jusqu'à ce que le dernier terme soit plus petit que 367 | 1e-15 (qui est la notation Python pour 10-15). Vous pouvez vérifier le résultat en le comparant à math.pi. 368 | Solution: [http://thinkpython2.com/code/pi.py](http://thinkpython2.com/code/pi.py) -------------------------------------------------------------------------------- /chapter07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/chapter07.pdf -------------------------------------------------------------------------------- /chapter08.md: -------------------------------------------------------------------------------- 1 | # Chapitre 8 2 | 3 | ## Les chaînes 4 |

5 | 6 | 7 | Les chaînes ne sont pas comme des entiers, des floats et des booléens. Une chaîne est une séquence, ce qui signifie qu'elle est une collection ordonnée d'autres valeurs. Dans ce chapitre, vous verrez comment accéder aux caractères qui constituent une chaîne, et vous apprendrez certaines des méthodes fournies par les chaînes. 8 | 9 | ## 8.1 Une chaîne est une séquence 10 | 11 | Une chaîne est une séquence de caractères. Vous pouvez accéder aux personnages un par un avec le 12 | opérateur de support []: 13 | 14 | ``` 15 | >>> fruit = 'banana' 16 | >>> letter = fruit[1] 17 | ``` 18 | 19 | La deuxième instruction sélectionne le numéro 1 du fruit et l'affecte à la lettre. 20 | L'expression entre parenthèses s'appelle un index. L'index indique quel caractère dans le 21 | séquence vous voulez (d'où le nom). 22 | Mais vous pourriez ne pas avoir ce que vous attendez: 23 | 24 | ``` 25 | >>> letter 26 | 'a' 27 | ``` 28 | 29 | Pour la plupart des gens, la première lettre de «banana» est b, pas a. Mais pour les informaticiens, l'index est un décalage par rapport au début de la chaîne et le décalage de la première lettre est zéro. 30 | ``` 31 | >>> letter = fruit[0] 32 | >>> letter 33 | 'b' 34 | ``` 35 | 36 | Donc b est la 0ème lettre ("zero-eth") de "banana", a est la 1ère lettre ("one-eth"), et n est le 2eme 37 | lettre ("two-eth"). 38 | En tant qu’index, vous pouvez utiliser une expression contenant des variables et des opérateurs: 39 | ``` 40 | >>> i = 1 41 | >>> fruit[i] 42 | 'a' 43 | >>> fruit[i+1] 44 | 'n' 45 | ``` 46 | 47 | Mais la valeur de l'index doit être un entier. Sinon, vous obtenez: 48 | 49 | ``` 50 | >>> letter = fruit[1.5] 51 | TypeError: string indices must be integers 52 | ``` 53 | 54 | ## 8.2 len 55 | 56 | len est une fonction intégrée qui renvoie le nombre de caractères d'une chaîne: 57 | ``` 58 | >>> fruit = 'banana' 59 | >>> len(fruit) 60 | 6 61 | ``` 62 | 63 | Pour obtenir la dernière lettre d'une chaîne, vous pourriez être tenté d'essayer quelque chose comme ceci: 64 | ``` 65 | >>> length = len(fruit) 66 | >>> last = fruit[length] 67 | IndexError: string index out of range 68 | ``` 69 | 70 | La raison de l’indexError est qu’il n’ya pas de lettre dans «banana» avec l’index 6. 71 | nous avons commencé à compter à zéro, les six lettres sont numérotées de 0 à 5. Pour obtenir le dernier caractère, 72 | vous devez soustraire 1 de la longueur: 73 | ``` 74 | >>> last = fruit[length-1] 75 | >>> last 76 | 'a' 77 | ``` 78 | Ou vous pouvez utiliser des index négatifs, qui comptent à partir de la fin de la chaîne. le 79 | expression fruit [-1] donne la dernière lettre, fruit [-2] renvoie la seconde à la dernière, et ainsi de suite. 80 | 81 | ## 8.3 Traversal avec une boucle for 82 | 83 | De nombreux calculs impliquent le traitement d'une chaîne par caractère. Ils commencent souvent 84 | au début, sélectionnez chaque caractèr à son tour, faites-lui quelque chose et continuez jusqu'à la 85 | fin. Ce modèle de traitement s'appelle une traversée. Une façon d'écrire une traversée est d'utiliser un 86 | un boucle: 87 | 88 | ```python 89 | index = 0 90 | while index < len(fruit): 91 | letter = fruit[index] 92 | print(letter) 93 | index = index + 1 94 | ``` 95 | Cette boucle traverse la chaîne et affiche chaque lettre sur une ligne. La condition de la boucle 96 | est index < len(fruit), donc quand index est égal à la longueur de la chaîne, la condition est 97 | false et le corps de la boucle ne s'exécute pas. Le dernier personnage accédé est celui avec l'index len (fruit) -1, qui est le dernier caractère de la chaîne. 98 | En tant qu’exercice, écrivez une fonction qui prend une chaîne comme argument et affiche les lettres 99 | en arrière, un par ligne. 100 | Une autre façon d'écrire une traversée consiste à utiliser une boucle for: 101 | 102 | ```python 103 | for letter in fruit: 104 | print(letter) 105 | ``` 106 | 107 | A chaque fois dans la boucle, le caractère suivant de la chaîne est assigné à la variable 108 | letter. La boucle continue jusqu'à ce qu'il ne reste plus aucun caractère. 109 | L'exemple suivant montre comment utiliser la concaténation (ajout de chaîne) et une boucle for 110 | pour générer une série abécédaire (c'est-à-dire par ordre alphabétique). Dans le livre de Robert McCloskey's 111 | Make Way for Ducklings, les noms des canetons sont Jack, Kack, Lack, Mack, Nack, 112 | Ouack, Pack et Quack. Cette boucle génère ces noms dans l'ordre: 113 | 114 | ```python 115 | prefixes = 'JKLMNOPQ' 116 | suffix = 'ack' 117 | 118 | for letter in prefixes: 119 | print(letter + suffix) 120 | ``` 121 | The output is: 122 | ``` 123 | Jack 124 | Kack 125 | Lack 126 | Mack 127 | Nack 128 | Oack 129 | Pack 130 | Qack 131 | ``` 132 | 133 | Bien sûr, ce n'est pas tout à fait correct, car "Ouack" et "Quack" sont mal orthographiés. En tant qu'exercice, 134 | modifiez le programme pour corriger cette erreur. 135 | 136 | ## 8.4 Tranches de chaîne 137 | 138 | Un segment d'une chaîne est appelé une tranche. La sélection d'une tranche est similaire à la sélection d'un caractère: 139 | 140 | ``` 141 | >>> s = 'Monty Python' 142 | >>> s [0: 5] 143 | 'Monty' 144 | >>> s [6:12] 145 | 'Python' 146 | ``` 147 | 148 | L'opérateur [n: m] renvoie la partie de la chaîne du caractère "n-eth" au "m-eth" 149 | , y compris le premier mais excluant le dernier. Ce comportement est contre-intuitif, mais 150 | il pourrait être utile d'imaginer les indices pointant entre les caractères, comme dans la figure 8.1. 151 | 152 | ![fig8.1](assets/tp8.1.png) 153 | 154 | Si vous omettez le premier index (avant les deux points), la tranche commence au début de la chaîne. 155 | Si vous omettez le deuxième index, la tranche va à la fin de la chaîne: 156 | ``` 157 | >>> fruit = 'banana' 158 | >>> fruit[:3] 159 | 'ban' 160 | >>> fruit[3:] 161 | 'ana' 162 | ``` 163 | Si le premier index est supérieur ou égal au second, le résultat est une chaîne vide, représentée par deux guillemets: 164 | ``` 165 | >>> fruit = 'banana' 166 | >>> fruit[3:3] 167 | '' 168 | ``` 169 | Une chaîne vide ne contient aucun caractère et a la longueur 0, mais à part ça, c'est la même chose 170 | comme toute autre chaîne. 171 | Poursuivant cet exemple, à votre avis, que veut dire fruit [:]? Essayez-le et voyez. 172 | 173 | ## 8.5 Les caractères sont immuables 174 | 175 | Il est tentant d’utiliser l’opérateur [] à gauche d’une affectation, avec l’intention de 176 | changer un caractère dans une chaîne. Par exemple: 177 | ``` 178 | >>> greeting = 'Hello, world!' 179 | >>> greeting[0] = 'J' 180 | TypeError: 'str' object does not support item assignment 181 | ``` 182 | Le "objet" dans ce cas est la chaîne et "l'élément" est le caractère que vous avez essayé d'attribuer. 183 | Pour l'instant, un objet est la même chose qu'une valeur, mais nous affinerons cette définition ultérieurement 184 | (Section 10.10). 185 | La raison de l'erreur est que les chaînes sont immuables, ce qui signifie que vous ne pouvez pas changer un 186 | chaîne existante. Le mieux que vous puissiez faire est de créer une nouvelle chaîne qui est une variante de l'original: 187 | ``` 188 | >>> greeting = 'Hello, world!' 189 | >>> new_greeting = 'J' + greeting[1:] 190 | >>> new_greeting 191 | 'Jello, world!' 192 | ``` 193 | Cet exemple concatène une nouvelle première lettre sur une tranche de message d'accueil. Cela n'a aucun effet sur le 194 | chaîne originale. 195 | 196 | ## 8.6 Recherche 197 | 198 | Que fait la fonction suivante? 199 | 200 | ```python 201 | def find(word, letter): 202 | index = 0 203 | while index < len(word): 204 | if word[index] == letter: 205 | return index 206 | index = index + 1 207 | return -1 208 | ``` 209 | 210 | En un sens, find est l'inverse de l'opérateur []. Au lieu de prendre un index et d’extraire 211 | le caractère correspondant, il prend un caractère et trouve l'index où ce caractère 212 | apparaît. Si le caractère n'est pas trouvé, la fonction renvoie -1. 213 | C'est le premier exemple que nous avons vu d'une déclaration de retour dans une boucle. Si mot [index] 214 | == lettre, la fonction sort de la boucle et revient immédiatement. 215 | Si le caractère n'apparaît pas dans la chaîne, le programme quitte la boucle normalement et renvoie -1. 216 | Ce modèle de calcul-traversant une séquence et retournant quand on trouve ce que l'on 217 | recherche-est appelé une recherche. 218 | En tant qu’exercice, modifiez la recherche pour qu’elle ait un troisième paramètre, l’index dans le mot où l'on devrait commencer à regarder. 219 | 220 | ## 8.7 En boucle et compter 221 | 222 | Le programme suivant compte le nombre de fois que la lettre a apparaît dans une chaîne: 223 | ```python 224 | word = 'banana' 225 | count = 0 226 | for letter in word: 227 | if letter == 'a': 228 | count = count + 1 229 | print(count) 230 | ``` 231 | 232 | Ce programme montre un autre modèle de calcul appelé compteur. La variable 233 | count est initialisé à 0 puis incrémenté chaque fois qu'un a est trouvé. Lorsque la boucle se termine, 234 | count contient le résultat - le nombre total de a. 235 | En guise d’exercice, encapsulez ce code dans une fonction nommée count et généralisez-le pour qu'il 236 | accepte la chaîne et la lettre comme arguments. 237 | Ensuite, réécrivez la fonction de sorte que, au lieu de parcourir la chaîne, elle utilise la version à trois paramètres de find de la section précédente. 238 | 239 | ## 8.8 Méthodes de chaîne 240 | 241 | Les chaînes fournissent des méthodes permettant d'effectuer diverses opérations utiles. Une méthode est similaire 242 | à une fonction, elle prend des arguments et retourne une valeur, mais la syntaxe est différente. Pour 243 | Par exemple, la méthode upper prend une chaîne et retourne une nouvelle chaîne avec toutes les majuscules 244 | des lettres. 245 | Au lieu de la syntaxe de fonction upper(mot), elle utilise la syntaxe de la méthode word.upper(). 246 | ``` 247 | >>> word = 'banana' 248 | >>> new_word = word.upper() 249 | >>> new_word 250 | 'BANANA' 251 | ``` 252 | 253 | Cette forme de notation par points spécifie le nom de la méthode, supérieure et le nom de la 254 | chaîne pour appliquer la méthode à, mot. Les parenthèses vides indiquent que cette méthode 255 | ne prend aucun argument. 256 | Un appel de méthode est appelé une invocation; dans ce cas, nous dirions que nous invoquons 257 | supérieur sur le mot. 258 | Comme il se trouve, il existe une méthode de chaîne nommée find qui est remarquablement similaire à la 259 | fonction nous avons écrit: 260 | ``` 261 | >>> word = 'banana' 262 | >>> index = word.find('a') 263 | >>> index 264 | 1 265 | ``` 266 | Dans cet exemple, nous invoquons find sur word et transmettons la lettre que nous recherchons en tant que paramètre. 267 | En fait, la méthode de recherche est plus générale que notre fonction; il peut trouver des sous-chaînes, pas seulement 268 | personnages: 269 | ``` 270 | >>> word.find ('na') 271 | 2 272 | ``` 273 | Par défaut, find commence au début de la chaîne, mais il peut prendre un deuxième argument, l'index où il devrait commencer: 274 | ``` 275 | >>> word.find ('na', 3) 276 | 4 277 | ``` 278 | Ceci est un exemple d'un argument optionnel; find peut aussi prendre un troisième argument, l'index 279 | où il devrait s'arrêter: 280 | ``` 281 | >>> name = 'bob' 282 | >>> name.find ('b', 1, 2) 283 | -1 284 | ``` 285 | Cette recherche échoue car b n'apparaît pas dans la plage d'index de 1 à 2, sans inclure 2. 286 | Recherche jusqu'au, mais non compris, le deuxième index rend la recherche cohérente avec l'opérateur de 287 | tranche. 288 | 289 | ## 8.9 L'opérateur in 290 | 291 | Le mot in est un opérateur booléen qui prend deux chaînes et renvoie True si le premier apparaît comme une sous-chaîne dans le second: 292 | 293 | ``` 294 | >>> 'a' in 'banana' 295 | True 296 | >>> 'seed' in 'banana' 297 | False 298 | ``` 299 | 300 | Par exemple, la fonction suivante imprime toutes les lettres de word1 qui apparaissent également dans 301 | mot2: 302 | 303 | ``` 304 | def in_both(word1, word2): 305 | for letter in word1: 306 | if letter in word2: 307 | print(letter) 308 | ``` 309 | 310 | Avec des noms de variables bien choisis, Python se lit parfois comme l'anglais. Vous pouvez lire 311 | cette boucle, "pour (chaque) lettre dans (le premier) mot, si (la) lettre (apparaît) dans (le second) mot, 312 | imprimer la lettre. " 313 | Voici ce que vous obtenez si vous comparez des pommes et des oranges: 314 | 315 | >>> in_both('apples', 'oranges') 316 | a 317 | e 318 | s 319 | 320 | ## 8.10 Comparaison de chaîne 321 | 322 | Les opérateurs relationnels travaillent sur des chaînes. Pour voir si deux chaînes sont égales: 323 | ``` 324 | if word == 'banana': 325 | print('All right, bananas.') 326 | ``` 327 | D'autres opérations relationnelles sont utiles pour mettre les mots en ordre alphabétique: 328 | 329 | ```python 330 | if word < 'banana': 331 | print('Your word, ' + word + ', comes before banana.') 332 | elif word > 'banana': 333 | print('Your word, ' + word + ', comes after banana.') 334 | else: 335 | print('All right, bananas.') 336 | ``` 337 | 338 | Python ne gère pas les lettres majuscules et minuscules de la même manière que les gens. Tous les 339 | les lettres majuscules viennent avant toutes les lettres minuscules, donc: 340 | 341 | Votre mot, ananas, vient avant la banane. 342 | Une méthode courante pour résoudre ce problème consiste à convertir des chaînes en un format standard, tel que 343 | tout en minuscule, avant d'effectuer la comparaison. Gardez cela à l'esprit au cas où vous devriez 344 | Défendez-vous contre un homme armé d'un Ananas. 345 | 346 | ## 8.11 Le débogage 347 | 348 | Lorsque vous utilisez des indices pour parcourir les valeurs dans une séquence, il est difficile de bien cerner le commencement et la fin du parcours. Voici une fonction censée comparer deux mots 349 | et retourner True si l'un des mots est l'inverse de l'autre, mais il contient deux erreurs: 350 | 351 | ```python 352 | def is_reverse(word1, word2): 353 | if len(word1) != len(word2): 354 | return False 355 | 356 | i = 0 357 | j = len(word2) 358 | 359 | while j > 0: 360 | if word1[i] != word2[j]: 361 | return False 362 | i = i+1 363 | j = j-1 364 | 365 | return True 366 | ``` 367 | 368 | La première instruction if vérifie si les mots ont la même longueur. Sinon, nous pouvons retourner 369 | False immédiatement Sinon, pour le reste de la fonction, on peut supposer que les mots 370 | sont la même longueur Ceci est un exemple du modèle de gardien dans la section 6.8. 371 | i et j sont des indices: i traverse mot1 en avant tandis que j traverse mot2 en arrière. Si nous 372 | trouver deux lettres qui ne correspondent pas, nous pouvons retourner False immédiatement. Si nous passons à travers la 373 | boucle entière et toutes les lettres correspondent, nous retournons True. 374 | Si nous testons cette fonction avec les mots "pots" et "stop", nous attendons la valeur de retour True, 375 | mais nous obtenons un IndexError: 376 | ``` 377 | >>> is_reverse('pots', 'stop') 378 | ... 379 | File "reverse.py", line 15, in is_reverse 380 | if word1[i] != word2[j]: 381 | IndexError: string index out of range 382 | ``` 383 | 384 | Pour déboguer ce genre d'erreur, je commence par imprimer les valeurs des indices immédiatement avant la ligne où l'erreur apparaît. 385 | ```python 386 | while j > 0: 387 | print(i, j) # print here 388 | 389 | if word1[i] != word2[j]: 390 | return False 391 | i = i+1 392 | j = j-1 393 | ``` 394 | Maintenant, lorsque je relance le programme, je reçois plus d'informations: 395 | ``` 396 | >>> is_reverse('pots', 'stop') 397 | 0 4 398 | ... 399 | IndexError: string index out of range 400 | ``` 401 | La première fois dans la boucle, la valeur de j est 4, ce qui est hors de portée pour le 402 | chaîne 'pots'. L'index du dernier caractère est 3, donc la valeur initiale de j devrait être 403 | len (word2) -1. 404 | Si je corrige cette erreur et lance à nouveau le programme, j'obtiens: 405 | ``` 406 | >>> is_reverse ('pots', 'stop') 407 | 0 3 408 | 1 2 409 | 2 1 410 | True 411 | ``` 412 | Cette fois, nous obtenons la bonne réponse, mais il semble que la boucle ne soit exécutée que trois fois, ce qui est 413 | méfiant. Pour avoir une meilleure idée de ce qui se passe, il est utile de dessiner un diagramme d'état. 414 | Au cours de la première itération, le cadre de is_reverse est illustré à la figure 8.2. 415 | 416 | ![fig8.2](assets/tp8.2.png) 417 | 418 | J'ai pris une licence en organisant les variables dans le cadre et en ajoutant des lignes pointillées pour montrer 419 | que les valeurs de i et j indiquent des caractères dans word1 et word2. 420 | À partir de ce diagramme, lancez le programme sur papier en changeant les valeurs de i et j 421 | lors de chaque itération. Recherchez et corrigez la deuxième erreur dans cette fonction. 422 | 423 | ## 8.12. Glossaire 424 | 425 | - **objet:** quelque chose auquel une variable peut se référer. Pour l'instant, vous pouvez utiliser "objet" et "valeur" 426 | indifféremment. 427 | 428 | - **sequence:** Collection ordonnée de valeurs où chaque valeur est identifiée par un entier 429 | indice. 430 | 431 | - **item:** Une des valeurs d'une séquence. 432 | 433 | - **index:** valeur entière utilisée pour sélectionner un élément dans une séquence, tel qu'un caractère dans une chaîne. 434 | Dans Python, les index commencent à 0. 435 | 436 | - **slice:** partie d'une chaîne spécifiée par une plage d'indices. 437 | 438 | - **chaîne vide:** Chaîne sans caractères et longueur 0, représentée par deux guillemets 439 | des notes. 440 | 441 | - **immutable:** La propriété d'une séquence dont les éléments ne peuvent pas être modifiés. 442 | 443 | - **traverse:** pour parcourir les éléments d'une séquence, en effectuant une opération similaire sur 444 | chaque. 445 | 446 | - **search:** Un modèle de parcours qui s'arrête lorsqu'il trouve ce qu'il cherche. 447 | 448 | - **counter:** variable utilisée pour compter quelque chose, généralement initialisée à zéro puis incrémentée. 449 | 450 | - **invocation:** une instruction qui appelle une méthode. 451 | 452 | - **argument optionnel:** argument de fonction ou de méthode non requis. 453 | 454 | ## 8.13 Exercices 455 | 456 | **Exercice 8.1** 457 | 458 | Lisez la documentation des méthodes de chaîne à l'adresse [http://docs.python.org/3/library/stdtypes.html#string-methods](http://docs.python.org/3/library/stdtypes.html#string-methods). Vous pourriez vouloir expérimenter avec certains d'entre eux 459 | pour vous assurer que vous comprenez comment ils fonctionnent. strip et replace sont particulièrement utiles. 460 | La documentation utilise une syntaxe qui peut être source de confusion. 461 | Par exemple, dans 462 | find (sub [, start [, end]]), les crochets indiquent des arguments facultatifs. Donc sub est requis, mais 463 | start est optionnel, et si vous incluez start, alors end est optionnel. 464 | 465 | **Exercice 8.2** 466 | 467 | Il existe une méthode de chaîne appelée count qui est similaire à la fonction de la section 8.7. 468 | Lisez la documentation de cette méthode et écrivez une invocation qui compte le nombre de 469 | 'banane'. 470 | 471 | **Exercice 8.3** 472 | 473 | Une tranche de chaîne peut prendre un troisième index qui spécifie la "taille de pas"; c'est-à-dire le nombre 474 | des espaces entre les caractères successifs. Un pas de 2 signifie tous les autres caractères; 3 signifie tous les 475 | troisième, etc. 476 | 477 | ``` 478 | >>> fruit = 'banana' 479 | >>> fruit[0:5:2] 480 | 'bnn' 481 | ``` 482 | Une taille de pas de -1 traverse le mot en arrière, de sorte que la tranche [:: - 1] génère une chaîne inversée. 483 | Utilisez cet idiome pour écrire une version d'une ligne de is_palindrome à partir de l'exercice 6.3. 484 | Exercice 8.4. Les fonctions suivantes sont toutes destinées à vérifier si une chaîne contient des 485 | lettres minuscules, mais au moins certaines d'entre elles sont fausses. Pour chaque fonction, décrivez ce que la fonction 486 | fait (en supposant que le paramètre est une chaîne). 487 | 488 | ```python 489 | def any_lowercase1(s): 490 | for c in s: 491 | if c.islower(): 492 | return True 493 | else: 494 | return False 495 | 496 | def any_lowercase2(s): 497 | for c in s: 498 | if 'c'.islower(): 499 | return 'True' 500 | else: 501 | return 'False' 502 | 503 | def any_lowercase3(s): 504 | for c in s: 505 | flag = c.islower() 506 | return flag 507 | 508 | def any_lowercase4(s): 509 | flag = False 510 | for c in s: 511 | flag = flag or c.islower() 512 | return flag 513 | 514 | def any_lowercase5(s): 515 | for c in s: 516 | if not c.islower(): 517 | return False 518 | return True 519 | ``` 520 | **Exercice 8.5** 521 | 522 | Un cryptage César est une forme de cryptage faible qui consiste à "faire tourner" chaque lettre de 523 | un nombre fixe de places. Faire pivoter une lettre signifie la déplacer dans l’alphabet 524 | au début si nécessaire, 'A' pivoté de 3 est 'D' et 'Z' tourné de 1 est 'A'. 525 | Pour faire pivoter un mot, faites pivoter chaque lettre du même montant. Par exemple, "cheer" pivoté de 7 est "jolly" 526 | et "melon" tourné de -10 est "cubed". Dans le film 2001: Odyssée de l'espace, l'ordinateur de bord 527 | est appelée HAL, qui est tournée de -1 par IBM. 528 | Ecrire une fonction appelée rotate_word qui prend une chaîne et un entier comme paramètres et renvoie 529 | une nouvelle chaîne contenant les lettres de la chaîne d'origine pivotée par la quantité donnée. 530 | Vous voudrez peut-être utiliser la fonction intégrée ord, qui convertit un caractère en code numérique, et 531 | chr, qui convertit les codes numériques en caractères. Les lettres de l'alphabet sont codées par ordre alphabétique 532 | ordre, par exemple: 533 | ``` 534 | >>> ord ('c') - ord ('a') 535 | 2 536 | ``` 537 | Parce que "c" est la lettre de deux éthiques de l'alphabet. Mais attention: les codes numériques pour les majuscules 538 | les minuscules sont différentes. 539 | 540 | Les blagues potentiellement choquantes sur Internet sont parfois encodées dans ROT13, qui est une César 541 | cypher avec rotation 13. Si vous n'êtes pas facilement offensé, trouvez et décodez certains d'entre eux. Solution: [http://thinkpython2.com/code/rotate.py](http://thinkpython2.com/code/rotate.py). -------------------------------------------------------------------------------- /completed_upto_now.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/completed_upto_now.pdf -------------------------------------------------------------------------------- /desktop.ini: -------------------------------------------------------------------------------- 1 | [ViewState] 2 | Mode= 3 | Vid= 4 | FolderType=Generic 5 | -------------------------------------------------------------------------------- /mdtohtml.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | 4 | import jinja2 5 | import markdown 6 | 7 | TEMPLATE = """ 8 | 9 | 10 | 11 | 12 | 14 | 17 | 18 | 19 |
20 | 21 | {{content}} 22 | 23 | 24 | 25 |
26 | 27 | 28 | """ 29 | 30 | ''' 31 | def parse_args(args=None): 32 | d = 'Make a complete, styled HTML document from a Markdown file.' 33 | parser = argparse.ArgumentParser(description=d) 34 | parser.add_argument('mdfile', type=argparse.FileType('r'), nargs='?', 35 | default=sys.stdin, 36 | help='File to convert. Defaults to stdin.') 37 | parser.add_argument('-o', '--out', type=argparse.FileType('w'), 38 | default=sys.stdout, 39 | help='Output file name. Defaults to stdout.') 40 | return parser.parse_args(args) 41 | 42 | 43 | def main(args=None): 44 | print('[x] capturing args ...') 45 | args = parse_args(args) 46 | 47 | md = args.mdfile.read() 48 | print('[x] fetching extentions ...') 49 | extensions = ['extra', 'smarty'] 50 | print('[x] converting to html ...') 51 | html = markdown.markdown(md, extensions=extensions, output_format='html5') 52 | print('[x] rendering with jinja ...') 53 | doc = jinja2.Template(TEMPLATE).render(content=html) 54 | print('[x] writing ...') 55 | args.out.write(doc) 56 | print('Terminated') 57 | ''' 58 | 59 | mdfile = sys.argv[1] 60 | 61 | def main(args=None): 62 | print('[x] reading md file ...') 63 | with open(mdfile, 'r', encoding='utf8') as f: 64 | md = f.read() 65 | print('[x] fetching extentions ...') 66 | extensions = ['extra', 'smarty'] 67 | print('[x] converting to html ...') 68 | html = markdown.markdown(md, extensions=extensions, output_format='html5') 69 | print('[x] rendering template ...') 70 | doc = jinja2.Template(TEMPLATE).render(content=html) 71 | print('[x] writing ...') 72 | with open(mdfile[:-3]+'.html', 'w+', encoding='utf8') as f: 73 | f.write(doc) 74 | print('Terminated') 75 | 76 | 77 | if __name__ == '__main__': 78 | sys.exit(main()) -------------------------------------------------------------------------------- /newf.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/newf.md -------------------------------------------------------------------------------- /ooo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdur-rahmaanJ/Think-Python-Fr/8e52444e9776d479c611648b277459af6a6748a9/ooo.pdf -------------------------------------------------------------------------------- /script.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | 4 | import jinja2 5 | import markdown 6 | 7 | TEMPLATE = """ 8 | 9 | 10 | 11 | 12 | 14 | 17 | 18 | 19 |
20 | 21 | {{content}} 22 | 23 | 24 | 25 |
26 | 27 | 28 | """ 29 | 30 | ''' 31 | def parse_args(args=None): 32 | d = 'Make a complete, styled HTML document from a Markdown file.' 33 | parser = argparse.ArgumentParser(description=d) 34 | parser.add_argument('mdfile', type=argparse.FileType('r'), nargs='?', 35 | default=sys.stdin, 36 | help='File to convert. Defaults to stdin.') 37 | parser.add_argument('-o', '--out', type=argparse.FileType('w'), 38 | default=sys.stdout, 39 | help='Output file name. Defaults to stdout.') 40 | return parser.parse_args(args) 41 | 42 | 43 | def main(args=None): 44 | print('[x] capturing args ...') 45 | args = parse_args(args) 46 | 47 | md = args.mdfile.read() 48 | print('[x] fetching extentions ...') 49 | extensions = ['extra', 'smarty'] 50 | print('[x] converting to html ...') 51 | html = markdown.markdown(md, extensions=extensions, output_format='html5') 52 | print('[x] rendering with jinja ...') 53 | doc = jinja2.Template(TEMPLATE).render(content=html) 54 | print('[x] writing ...') 55 | args.out.write(doc) 56 | print('Terminated') 57 | ''' 58 | 59 | def main(args=None): 60 | print('[x] reading md file ...') 61 | with open('completed_upto_now.md', 'r', encoding='utf8') as f: 62 | md = f.read() 63 | print('[x] fetching extentions ...') 64 | extensions = ['extra', 'smarty'] 65 | print('[x] converting to html ...') 66 | html = markdown.markdown(md, extensions=extensions, output_format='html5') 67 | print('[x] rendering template ...') 68 | doc = jinja2.Template(TEMPLATE).render(content=html) 69 | print('[x] writing ...') 70 | with open('completed_upto_now.html', 'w+', encoding='utf8') as f: 71 | f.write(doc) 72 | print('Terminated') 73 | 74 | 75 | if __name__ == '__main__': 76 | sys.exit(main()) --------------------------------------------------------------------------------