Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
Это архивный репозиторий. Вы можете его клонировать или просматривать файлы, но не вносить изменения или открывать задачи/запросы на слияние.

5 лет назад
5 лет назад
5 лет назад
5 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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. # Découper les mots
  48. Dans la liste se trouvent des mots mal découpés:
  49. * `peutétre`
  50. * `lhumanité`
  51. Reprenons depuis le début
  52. # Tester chaque fonction une par une
  53. * Spécification
  54. * Test
  55. * Implémentation
  56. # Découpage en fragments - spécification
  57. On a:
  58. > L'univers est, peut-être, « infini! »
  59. On veut:
  60. ```python
  61. ["l", "univers", "est", "peut-être", '«', "infini", '»']
  62. ```
  63. On s'occupera d'enlever la ponctuation plus tard.
  64. # Découpage en fragments - test
  65. ```python
  66. contents = "L'unives est, peut-être, infini!"
  67. fragments = split_fragments(contents)
  68. print(fragments)
  69. ```
  70. # Découpage en fragments - implémentation
  71. ```python
  72. def split_fragments(contents):
  73. res = list()
  74. for fragment in contents.split():
  75. if "’" in fragment:
  76. (before, after) = fragment.split("’")
  77. res.append(before)
  78. res.append(after)
  79. else:
  80. res.append(fragment)
  81. return res
  82. ```
  83. # Découpage en mots - spécification
  84. On a:
  85. ```
  86. L'unives est, peut-être, « infini! »
  87. ```
  88. On veut:
  89. ```
  90. ['l', 'unives', 'est', 'peut-être', 'infini']
  91. ```
  92. # Découpage en mots - test
  93. ```python
  94. contents = "L'univers est, peut-être, « infini! »"
  95. words = split_words(contents)
  96. print(words)
  97. ```
  98. # Découpage en mots - implémentation
  99. On peut reprendre le code vu ensemble,
  100. avec quelques modifications:
  101. ```python
  102. def split_words(text):
  103. fragments = split_fragments(text)
  104. res = list()
  105. for fragment in fragments:
  106. fragment = fragment.lower()
  107. fragment = clean_fragment(fragment)
  108. if fragment: # le fragment peut-être vide ici
  109. res.append(fragment)
  110. return res
  111. ```
  112. # clean_fragment()
  113. Juste une petite modification:
  114. ```python
  115. def clean_fragment(fragment):
  116. result = ""
  117. for c in fragment:
  118. # autorise les tirets et apostrophes à l'intérieur
  119. # des mots
  120. if c.isalpha() or c in ["-", "'"]:
  121. result += c
  122. return result
  123. ```
  124. # Calcul des fréquences - spécification
  125. On a:
  126. ```python
  127. ["pomme", "poire", "banane", "poire", "banane", "banane"]`
  128. ```
  129. On veut:
  130. ```python
  131. {"pomme": 1, "poire": 2, "banane": 3}
  132. ```
  133. \vfill
  134. Note: par encore d'ordre ici!
  135. # Calcul des fréquences - test
  136. ```python
  137. words = [
  138. "pomme", "poire", "banane",
  139. "poire", "banane", "banane"
  140. ]
  141. frequencies = get_frequencies(words)
  142. print(frequencies)
  143. ```
  144. # Calcul des fréquences - implémentation
  145. ```python
  146. def get_frequencies(words):
  147. res = dict()
  148. for word in words:
  149. # Si le mot est déjà là, on incrémente
  150. # son compteur:
  151. if word in res:
  152. res[word] += 1
  153. else:
  154. # Sinon on crée une nouvelle clé
  155. # avec la valeur 1
  156. res[word] = 1
  157. return res
  158. ```
  159. # Tri - spécification
  160. On a:
  161. ```python
  162. {'pomme': 1, 'poire': 2, 'banane': 3}
  163. ```
  164. On veut:
  165. ```python
  166. [
  167. (3, 'banane'),
  168. (2, 'poire'),
  169. (1 'pomme'),
  170. ]
  171. ```
  172. # Tri - test
  173. ```python
  174. frequencies = {'pomme': 1, 'poire': 2, 'banane': 3}
  175. scores = get_scores(frequencies)
  176. print(scores)
  177. ```
  178. # Tri - implémentation
  179. ```python
  180. def get_scores(frequencies):
  181. res = list()
  182. for word, count in frequencies.items():
  183. res.append((count, word))
  184. res.sort(reverse=True)
  185. return res
  186. ```
  187. # Affichage des résultats
  188. On a :
  189. ```python
  190. scores = [
  191. (20, "banane"),
  192. (19, "poire"),
  193. ...
  194. ]
  195. ```
  196. On veut:
  197. ```
  198. 20 banane
  199. 19 poire
  200. ```
  201. # Affichage des résultats - test
  202. ```python
  203. scores = [
  204. (20, "banane"),
  205. (19, "poire"),
  206. ...
  207. ]
  208. print_scores(scores)
  209. ```
  210. # Affichage des résultats - implémentation
  211. ```python
  212. def print_scores(scores):
  213. for count, word in scores:
  214. print(count, word)
  215. ```
  216. # Assemblons les morceaux
  217. ```python
  218. def main():
  219. filename = "ruffin.txt"
  220. file = open(filename)
  221. contents = file.read()
  222. words = split_words(contents)
  223. frequencies = get_frequencies(words)
  224. scores = get_scores(frequencies)
  225. top_words = scores[:20] # le top 20
  226. print_scores(top_words)
  227. main()
  228. ```
  229. # Touches finales
  230. C'est bien si le nom du fichier est lu depuis la ligne de commande:
  231. ```python
  232. import sys
  233. def main():
  234. if len(sys.argv) < 2:
  235. sys.exit("not enough arguments")
  236. filename = sys.argv[1]
  237. ...
  238. ```
  239. #
  240. \center \huge Compléments - tris
  241. # sort() - ordre naturel
  242. ```python
  243. >>> nombres = [2, 3, 1, 5]
  244. >>> nombres.sort()
  245. >>> nombres
  246. [1, 2, 3, 5]
  247. ```
  248. Notez que la liste est modifiée *sur place*.
  249. # sort() - ordre alphabétique
  250. ```python
  251. >>> mots = ["abeille", "faucon", "chat"]
  252. >>> mots.sort()
  253. >>> mots
  254. ['abeille', 'chat', 'faucon']
  255. ```
  256. # sort() - ordre lexicographique
  257. Pour chaque "liste-élément" on compare le premier élément.
  258. S'il y a égalité, on regarde le deuxième élément, etc:
  259. ```python
  260. >>> composite = [["chat", 1], ["abeille", 2], ["chat", 3]]
  261. >>> composite.sort()
  262. >>> composite
  263. [['abeille', 2], ['chat', 1], ['chat', 3]]
  264. ```
  265. L'ordre alphabétique est l'ordre lexicographique pour les chaînes de caractères :)
  266. # Attention!
  267. Tous les éléments de la liste doivent être comparables deux à deux:
  268. \vfill
  269. ```python
  270. >>> mauvaise_liste = ["un", 2]
  271. >>> mauvaise_liste.sort()
  272. TypeError
  273. ```
  274. # Comparer autrement
  275. Exemple: trier les mots par leur taille avec l'argument `key`
  276. \vfill
  277. ```python
  278. def taille(mot):
  279. return len(mot)
  280. mots = ["chat", "abeille", "faucon"]
  281. mots.sort(key=taille)
  282. >>> mots
  283. ["chat", "faucon", "abeille"]
  284. ```
  285. # Lambda
  286. Sert définir une fonction sans utiliser `def`
  287. ```python
  288. >>> retourne_42 = lambda: 42 # pas d'argument
  289. >>> retourne_42()
  290. 42
  291. >>> ajoute_deux = lambda x: x + 2 # un seul argument
  292. >>> ajoute_deux(3)
  293. 5
  294. >>> multiplie = lambda x, y: x* y # deux arguments
  295. >>> multiplie(2, 3)
  296. 6
  297. ```
  298. Note: le corps de la fonction doit tenir en une seule ligne
  299. # Utilisation avec sort
  300. ```python
  301. >>> mots = ["chat", "abeille", "faucon"]
  302. >>> mots.sort(key=lambda x: len(x))
  303. >>> mots
  304. ["chat", "faucon", "abeille"]
  305. ```
  306. # sorted()
  307. ```python
  308. b = a.copy()
  309. b.sort()
  310. # or
  311. b = sorted(a)
  312. ```
  313. \center \huge Compléments - fichiers
  314. # Rappel: lire
  315. ```python
  316. file = open("toto.txt", "r") # 'r' comme 'read'
  317. contenu = file.read()
  318. file.close()
  319. ```
  320. Note: le fichier `toto.txt` doit exister!
  321. # Écrire
  322. On peut écrire tout le contenu d'un coup:
  323. ```python
  324. contenu = "du texte à sauvegarder"
  325. file = open("article.txt", "w") # 'w' comme 'write'
  326. file.write(contenu)
  327. file.close()
  328. ```
  329. * Le fichier `article.txt` sera écrasé s'il existe déjà.
  330. * N'oubliez surtout pas d'appeler `close()`
  331. # Que faire en cas d'erreur ?
  332. ```python
  333. file = open("article.txt", "w") # 'w' comme 'write'
  334. # ... beacoup de code ici
  335. # ... < une erreur
  336. file.close()
  337. ```
  338. S'il y a une erreur entre `open()` et `close()`, le fichier ne sera pas fermé!
  339. # Le mot-clé with
  340. ```python
  341. with open("toto.txt", "w") as file:
  342. file.write("du texte")
  343. ```
  344. Quand on sort du bloc `with` on a la garantie que `file.close()` sera appelé,
  345. *même* si on sort du bloc à cause d'une erreur.
  346. # Convention
  347. Il n'y a maintenant plus aucune raison d'appeler `.close()` "à la main",
  348. donc ne le faites pas ...
  349. # Lire et écrire des lignes
  350. Très courant:
  351. ```python
  352. with open("toto.txt", "r") as file:
  353. lignes = file.readlines()
  354. # faire quelque chose avec la liste de lignes
  355. with open("toto.txt", "w") as file:
  356. file.writelines(lignes)
  357. ```
  358. Pensez à fermer le premier fichier avant d'ouvrir le second.
  359. (ça marche même s'ils ont le même nom)