Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
Dieses Repo ist archiviert. Du kannst Dateien sehen und es klonen, kannst aber nicht pushen oder Issues/Pull-Requests öffnen.

python-05.md 8.8 KiB

vor 5 Jahren
vor 5 Jahren
vor 5 Jahren
vor 5 Jahren
vor 5 Jahren
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. % Programmation avec Python (chapitre 5)
  2. % Dimitri Merejkowsky
  3. #
  4. \center \huge Suite de l'atelier précédent
  5. # Rappel
  6. Travail de la dernière fois.
  7. Les problèmes que j'ai vu:
  8. * noms
  9. * méthodologie
  10. #
  11. \center \huge naming
  12. # Quelques principes
  13. * L'un des problèmes les plus compliqué de l'informatique
  14. Tout en Anglais
  15. * Pas d'abbréviation
  16. * Pas de redondance
  17. # Exemples
  18. * `get_freq` -> `get_frequencies`
  19. * `nom_fich` -> `filename`
  20. * `list_frag` -> `fragments` # le pluriel nous dit que c'est une liste
  21. * `liste_mot` -> `words`
  22. Essayez de rester cohérents!
  23. # Exemples (2)
  24. ```python
  25. # Avant
  26. for fragment in list_frag:
  27. fragment_min = fragment.lower()
  28. frag_clean = clean(fragment_min)
  29. liste_mot.append(frag_clean)
  30. ```
  31. ```python
  32. # Après
  33. for fragment in fragments:
  34. fragment = fragment.lower()
  35. fragment = clean(fragment)
  36. liste_mot.append(fragment)
  37. ```
  38. On peut ré-utiliser le même nom plusieurs fois!
  39. #
  40. \center \huge Style
  41. # Espaces
  42. * Deux lignes entre chaque fonction
  43. * Des espaces autour des `=` pour les affectations
  44. * Pas d'espace quand c'est un argument nommé
  45. #
  46. \center \huge Repartons du début
  47. \normalsize (un genre de corrigé)
  48. # Revoir les changements chez vous
  49. Vous pourrez voir la suite des changements sur github:
  50. https://github.com/E2L/cours-python/tree/master/sources/topwords/
  51. # Note importante
  52. En programmation, il y a très rarement une seule
  53. bonne réponse !
  54. Ceci n'est qu'une solution possible, et une *technique possible*
  55. pour arriver à cette solution ...
  56. # Découper les mots
  57. Dans la liste se trouvent des mots mal découpés:
  58. * `peutétre`
  59. * `lhumanité`
  60. Reprenons depuis le début
  61. # Tester chaque fonction une par une
  62. * Spécification
  63. * Test
  64. * Implémentation
  65. # Découpage en fragments - spécification
  66. On a:
  67. > L'univers est, peut-être, « infini! »
  68. On veut:
  69. ```python
  70. ["l", "univers", "est", "peut-être", '«', "infini", '»']
  71. ```
  72. On s'occupera d'enlever la ponctuation plus tard.
  73. # Découpage en fragments - test
  74. ```python
  75. contents = "L'unives est, peut-être, infini!"
  76. fragments = split_fragments(contents)
  77. print(fragments)
  78. ```
  79. # Découpage en fragments - implémentation
  80. ```python
  81. def split_fragments(contents):
  82. res = list()
  83. for fragment in contents.split():
  84. if "’" in fragment:
  85. (before, after) = fragment.split("’")
  86. res.append(before)
  87. res.append(after)
  88. else:
  89. res.append(fragment)
  90. return res
  91. ```
  92. # Découpage en mots - spécification
  93. On a:
  94. ```
  95. L'unives est, peut-être, « infini! »
  96. ```
  97. On veut:
  98. ```
  99. ['l', 'unives', 'est', 'peut-être', 'infini']
  100. ```
  101. # Découpage en mots - test
  102. ```python
  103. contents = "L'univers est, peut-être, « infini! »"
  104. words = split_words(contents)
  105. print(words)
  106. ```
  107. # Découpage en mots - implémentation
  108. On peut reprendre le code vu ensemble,
  109. avec quelques modifications:
  110. ```python
  111. def split_words(text):
  112. fragments = split_fragments(text)
  113. res = list()
  114. for fragment in fragments:
  115. fragment = fragment.lower()
  116. fragment = clean_fragment(fragment)
  117. if fragment: # le fragment peut-être vide ici
  118. res.append(fragment)
  119. return res
  120. ```
  121. # clean_fragment()
  122. Juste une petite modification:
  123. ```python
  124. def clean_fragment(fragment):
  125. result = ""
  126. for c in fragment:
  127. # autorise les tirets et apostrophes à l'intérieur
  128. # des mots
  129. if c.isalpha() or c in ["-", "'"]:
  130. result += c
  131. return result
  132. ```
  133. # Calcul des fréquences - spécification
  134. On a:
  135. ```python
  136. ["pomme", "poire", "banane", "poire", "banane", "banane"]`
  137. ```
  138. On veut:
  139. ```python
  140. {"pomme": 1, "poire": 2, "banane": 3}
  141. ```
  142. \vfill
  143. Note: par encore d'ordre ici!
  144. # Calcul des fréquences - test
  145. ```python
  146. words = [
  147. "pomme", "poire", "banane",
  148. "poire", "banane", "banane"
  149. ]
  150. frequencies = get_frequencies(words)
  151. print(frequencies)
  152. ```
  153. # Calcul des fréquences - implémentation
  154. ```python
  155. def get_frequencies(words):
  156. res = dict()
  157. for word in words:
  158. # Si le mot est déjà là, on incrémente
  159. # son compteur:
  160. if word in res:
  161. res[word] += 1
  162. else:
  163. # Sinon on crée une nouvelle clé
  164. # avec la valeur 1
  165. res[word] = 1
  166. return res
  167. ```
  168. # Tri - spécification
  169. On a:
  170. ```python
  171. {'pomme': 1, 'poire': 2, 'banane': 3}
  172. ```
  173. On veut:
  174. ```python
  175. [
  176. (3, 'banane'),
  177. (2, 'poire'),
  178. (1 'pomme'),
  179. ]
  180. ```
  181. # Tri - test
  182. ```python
  183. frequencies = {'pomme': 1, 'poire': 2, 'banane': 3}
  184. scores = get_scores(frequencies)
  185. print(scores)
  186. ```
  187. # Tri - implémentation
  188. ```python
  189. def get_scores(frequencies):
  190. res = list()
  191. for word, count in frequencies.items():
  192. res.append((count, word))
  193. res.sort(reverse=True)
  194. return res
  195. ```
  196. # Affichage des résultats
  197. On a :
  198. ```python
  199. scores = [
  200. (20, "banane"),
  201. (19, "poire"),
  202. ...
  203. ]
  204. ```
  205. On veut:
  206. ```
  207. 20 banane
  208. 19 poire
  209. ```
  210. # Affichage des résultats - test
  211. ```python
  212. scores = [
  213. (20, "banane"),
  214. (19, "poire"),
  215. ...
  216. ]
  217. print_scores(scores)
  218. ```
  219. # Affichage des résultats - implémentation
  220. ```python
  221. def print_scores(scores):
  222. for count, word in scores:
  223. print(count, word)
  224. ```
  225. # Assemblons les morceaux
  226. ```python
  227. def main():
  228. filename = "ruffin.txt"
  229. file = open(filename)
  230. contents = file.read()
  231. words = split_words(contents)
  232. frequencies = get_frequencies(words)
  233. scores = get_scores(frequencies)
  234. top_words = scores[:20] # le top 20
  235. print_scores(top_words)
  236. main()
  237. ```
  238. # Touches finales
  239. C'est bien si le nom du fichier est lu depuis la ligne de commande:
  240. ```python
  241. import sys
  242. def main():
  243. if len(sys.argv) < 2:
  244. sys.exit("not enough arguments")
  245. filename = sys.argv[1]
  246. ...
  247. ```
  248. #
  249. \center \huge Compléments - tris
  250. # sort() - ordre naturel
  251. ```python
  252. >>> nombres = [2, 3, 1, 5]
  253. >>> nombres.sort()
  254. >>> nombres
  255. [1, 2, 3, 5]
  256. ```
  257. Notez que la liste est modifiée *sur place*.
  258. # sort() - ordre alphabétique
  259. ```python
  260. >>> mots = ["abeille", "faucon", "chat"]
  261. >>> mots.sort()
  262. >>> mots
  263. ['abeille', 'chat', 'faucon']
  264. ```
  265. # sort() - ordre lexicographique
  266. Pour chaque "liste-élément" on compare le premier élément.
  267. S'il y a égalité, on regarde le deuxième élément, etc:
  268. ```python
  269. >>> composite = [["chat", 1], ["abeille", 2], ["chat", 3]]
  270. >>> composite.sort()
  271. >>> composite
  272. [['abeille', 2], ['chat', 1], ['chat', 3]]
  273. ```
  274. L'ordre alphabétique est l'ordre lexicographique pour les chaînes de caractères :)
  275. # Attention!
  276. Tous les éléments de la liste doivent être comparables deux à deux:
  277. \vfill
  278. ```python
  279. >>> mauvaise_liste = ["un", 2]
  280. >>> mauvaise_liste.sort()
  281. TypeError
  282. ```
  283. # Comparer autrement
  284. Exemple: trier les mots par leur taille avec l'argument `key`
  285. \vfill
  286. ```python
  287. def taille(mot):
  288. return len(mot)
  289. mots = ["chat", "abeille", "faucon"]
  290. mots.sort(key=taille)
  291. >>> mots
  292. ["chat", "faucon", "abeille"]
  293. ```
  294. # Lambda
  295. Sert définir une fonction sans utiliser `def`
  296. ```python
  297. >>> retourne_42 = lambda: 42 # pas d'argument
  298. >>> retourne_42()
  299. 42
  300. >>> ajoute_deux = lambda x: x + 2 # un seul argument
  301. >>> ajoute_deux(3)
  302. 5
  303. >>> multiplie = lambda x, y: x* y # deux arguments
  304. >>> multiplie(2, 3)
  305. 6
  306. ```
  307. Note: le corps de la fonction doit tenir en une seule ligne
  308. # Utilisation avec sort
  309. ```python
  310. >>> mots = ["chat", "abeille", "faucon"]
  311. >>> mots.sort(key=lambda x: len(x))
  312. >>> mots
  313. ["chat", "faucon", "abeille"]
  314. ```
  315. # sorted()
  316. ```python
  317. b = a.copy()
  318. b.sort()
  319. # or
  320. b = sorted(a)
  321. ```
  322. \center \huge Compléments - fichiers
  323. # Rappel: lire
  324. ```python
  325. file = open("toto.txt", "r") # 'r' comme 'read'
  326. contenu = file.read()
  327. file.close()
  328. ```
  329. Note: le fichier `toto.txt` doit exister!
  330. # Écrire
  331. On peut écrire tout le contenu d'un coup:
  332. ```python
  333. contenu = "du texte à sauvegarder"
  334. file = open("article.txt", "w") # 'w' comme 'write'
  335. file.write(contenu)
  336. file.close()
  337. ```
  338. * Le fichier `article.txt` sera écrasé s'il existe déjà.
  339. * N'oubliez surtout pas d'appeler `close()`
  340. # Que faire en cas d'erreur ?
  341. ```python
  342. file = open("article.txt", "w") # 'w' comme 'write'
  343. # ... beacoup de code ici
  344. # ... < une erreur
  345. file.close()
  346. ```
  347. S'il y a une erreur entre `open()` et `close()`, le fichier ne sera pas fermé!
  348. # Le mot-clé with
  349. ```python
  350. with open("toto.txt", "w") as file:
  351. file.write("du texte")
  352. ```
  353. Quand on sort du bloc `with` on a la garantie que `file.close()` sera appelé,
  354. *même* si on sort du bloc à cause d'une erreur.
  355. # Convention
  356. Il n'y a maintenant plus aucune raison d'appeler `.close()` "à la main",
  357. donc ne le faites pas ...
  358. # Lire et écrire des lignes
  359. Très courant:
  360. ```python
  361. with open("toto.txt", "r") as file:
  362. lignes = file.readlines()
  363. # faire quelque chose avec la liste de lignes
  364. with open("toto.txt", "w") as file:
  365. file.writelines(lignes)
  366. ```
  367. Pensez à fermer le premier fichier avant d'ouvrir le second.
  368. (ça marche même s'ils ont le même nom)
  369. #
  370. \center \huge Atelier 2
  371. # Problème à résoudre
  372. Garder une liste de scores persistent dans
  373. le jeu du pendu