You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

python-S02-E06.md 8.0 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. % Programmation avec Python (Épisode 6)
  2. % Dimitri Merejkowsky
  3. #
  4. \center \huge Modules
  5. # Un fichier = un module
  6. À un fichier `mon_module.py` correspond _toujours_ un module `mon_module`.
  7. (La réciproque n'est pas vraie)
  8. # Code dans un module
  9. ```python
  10. # Dans bonjour.py
  11. a = 42
  12. ```
  13. Le module `bonjour` contient contient un *attribut* `a`
  14. dont la valeur est 42.
  15. # Importer un module
  16. Avec le mot-clé `import`, suivi du nom du module,
  17. _sans guillemets_.
  18. ```python
  19. $ python
  20. >>> import bonjour
  21. >>> bonjour.a
  22. 42
  23. ```
  24. # Une fonction dans un module
  25. ```python
  26. # toujours dans bonjour.py
  27. a = 42
  28. def dire_bonjour():
  29. print("Bonjour!")
  30. ```
  31. # Appeler une fonction depuis un module
  32. ```python
  33. >>> import bonjour
  34. >>> bonjour.dire_bonjour()
  35. Bonjour!
  36. ```
  37. **note**: différent de `python3 bonjour.py`.
  38. # Interaction - 1
  39. ```python
  40. >>> import bonjour
  41. >>> bonjour.dire_bonjour()
  42. Bonjour!
  43. >>> bonjour.dire_bonjour()
  44. Bonjour!
  45. ```
  46. # Interaction - 2
  47. ```python
  48. >>> import bonjour
  49. >>> bonjour.a
  50. 42
  51. >>> bonjour.a = 36
  52. >>> bonjour.a
  53. 36
  54. ```
  55. # Les imports ne sont faits qu'une seule fois
  56. ```python
  57. # Dans bonjour.py
  58. print("Je suis le module bonjour!")
  59. ```
  60. ```python
  61. >>> import bonjour
  62. Je suis le module bonjour!
  63. >>> import bonjour
  64. <rien>
  65. ```
  66. # La bibliothèque standard
  67. La bibliothèque standard est une collection de modules directement utilisables fournis à l'installation de Python.
  68. Exemple: `sys`, `random`, ...
  69. Toute la bibliothèque standard est documentée - et la traduction en Français est en cours:
  70. https://docs.python.org/fr/3/library/index.html
  71. Mettez ce lien dans vos favoris - il vous sera très utile.
  72. # Le module sys
  73. Le module `sys` est disponible par défaut, et contient plusieurs variables
  74. utiles.
  75. On va parler ici de l'une d'entre elles: `argv`.
  76. # sys.argv avec un fichier
  77. `sys.argv` est une liste de chaînes de caractères, qui
  78. n'est *jamais vide*, et est utile quand on lance python
  79. avec un fichier source:
  80. ```python
  81. # Dans lancez_moi.py
  82. import sys
  83. def main():
  84. print(sys.argv)
  85. main()
  86. ```
  87. \vfill
  88. Le premier élément est alors le nom du fichier:
  89. ```bash
  90. $ python3 lancez_moi.py
  91. ["lancez_moi.py"]
  92. ```
  93. # sys.argv avec un fichier - 2
  94. Si on rajoute des mots après le nom du fichier, ils apparaissent dans `sys.argv`:
  95. ```python
  96. # dans lancez_moi.py
  97. import sys
  98. def main():
  99. print(sys.argv)
  100. main()
  101. ```
  102. \vfill
  103. ```bash
  104. $ python3 lancez_moi.py un deux trois
  105. ["lancez_moi.py", "un", "deux", "trois"]
  106. ```
  107. # Les scripts Python
  108. Pour interagir avec l'utilisateur, on a souvent utilisé `input()`, passer par
  109. `sys.argv` est plus commun.
  110. Exemple:
  111. ```bash
  112. $ python3 faire_le_café
  113. $ python3 faire_le_café --sans-sucre
  114. ```
  115. #
  116. \center \huge QCM
  117. #
  118. ```python
  119. def dire_bonjour():
  120. return "Bonjour"
  121. x = dire_bonjour()
  122. print(x)
  123. ```
  124. 1. Erreur
  125. 2. Affiche "Bonjour"
  126. \pause
  127. Réponse: 2
  128. #
  129. ```python
  130. def dire_bonjour():
  131. print("Bonjour")
  132. x = dire_bonjour()
  133. print(x)
  134. ```
  135. 1. Erreur
  136. 2. Affiche "Bonjour"
  137. 3. Affiche "Bonjour" puis "None"
  138. \pause
  139. Réponse: 3 - le premier print vient de l'appel de la fonction,
  140. comme la fonction ne renvoie rien (pas de `return`), x vaut
  141. None
  142. #
  143. ```python
  144. def dire_bonjour():
  145. return "Bonjour"
  146. dire_bonjour()
  147. ```
  148. 1. N'affiche rien
  149. 2. Affiche "Bonjour"
  150. 3. Affiche 'None"
  151. \pause
  152. Réponse 1 - la fonction renvoie une valeur, mais
  153. on n'en fait rien.
  154. #
  155. ```python
  156. # Dans mon_module.py
  157. ma_variable = 42
  158. ```
  159. ```python
  160. >>> import "mon_module"
  161. >>> print(ma_variable)
  162. ```
  163. 1. Erreur
  164. 2. Affiche '42'
  165. \pause
  166. Réponse 1: les noms de modules ne sont pas des strings!
  167. #
  168. ```python
  169. # Dans mon_module.py
  170. ma_variable = 42
  171. ```
  172. ```python
  173. >>> import mon_module
  174. >>> print(ma_variable)
  175. ```
  176. 1. Erreur
  177. 2. Affiche '42'
  178. \pause
  179. Réponse 1: `ma_variable` est un *attribut* de `mon_module`, elle n'est
  180. pas disponible en dehors.
  181. #
  182. ```python
  183. # Dans mon_module.py
  184. ma_variable = 42
  185. ```
  186. ```python
  187. import mon_module
  188. mon_module.ma_variable = 43
  189. print(mon_module.ma_variable)
  190. ```
  191. 1. Erreur
  192. 2. Affiche '43'
  193. \pause
  194. Réponse 2: on peut lire et écrire les attributs des modules
  195. importés!
  196. #
  197. ```python
  198. # Dans mon_script.py
  199. print(sys.argv[0])
  200. ```
  201. ```bash
  202. $ python mon_script mon_argument
  203. ```
  204. 1. Erreur
  205. 2. Affiche 'mon_script'
  206. \pause
  207. Réponse 1: il faut donner le vrai nom du fichier!
  208. #
  209. ```python
  210. # Dans mon_script.py
  211. print(sys.argv[0])
  212. ```
  213. ```bash
  214. $ python mon_script.py mon_argument
  215. ```
  216. 1. Erreur
  217. 2. Affiche 'mon_script'
  218. \pause
  219. Réponse 1: il faut importer `sys` avant de pouvoir l'utiliser
  220. #
  221. ```python
  222. # Dans mon_script.py
  223. import sys
  224. print(sys.argv[0])
  225. ```
  226. ```bash
  227. $ python mon_script.py mon_argument
  228. ```
  229. 1. Erreur
  230. 2. Affiche 'mon_argument'
  231. \pause
  232. C'est un piège! `argv[0]` est le chemin du script!
  233. #
  234. ```python
  235. # Dans mon_script.py
  236. import sys
  237. print(sys.argv[1])
  238. ```
  239. ```bash
  240. $ python mon_script.py mon_argument
  241. ```
  242. 1. Erreur
  243. 2. Affiche 'mon_argument'
  244. \pause
  245. Réponse 2 :)
  246. #
  247. ```python
  248. # Dans mon_script.py
  249. import sys
  250. print(sys.argv[1])
  251. ```
  252. ```bash
  253. $ python mon_script.py
  254. ```
  255. 1. Erreur
  256. 2. Affiche 'mon_script.py'
  257. \pause
  258. Réponse 1. `argv` a une taille 1, et on accède à l'index 1.
  259. #
  260. \center \huge Atelier
  261. # Introduction
  262. Vous allez jouer le rôle successivement d'un espion Bordure, puis d'un
  263. espion Syldave (les noms viennent de l'univers de Tintin), et l'atelier
  264. comporte trois parties.
  265. # Chiffrement v1
  266. Vous devez implémenter le script suivant, nommé `chiffrer.py`.
  267. Il se lance ainsi:
  268. ```bash
  269. $ python chiffrer.py n MESSAGE
  270. ```
  271. où `n` est en entier entre 0 et 25, et `MESSAGE` une chaîne de caractères
  272. non accentués.
  273. L'algorithme est le suivant:
  274. * Supprimer les espaces et les signes de ponctuation du message
  275. * Remplacer chaque lettre par une majuscule
  276. * Décaler chaque lettre du message en utilisant le pas `n`.
  277. Par exemple, si le message est `BONJOUR` et le pas 2, le message
  278. chiffré devient `DQPLQWT`.
  279. Notez que si on décale la lettre `Y` avec un pas de 3, on doit obtenir
  280. `B` (il faut effectuer une rotation)
  281. # Chiffrement v2
  282. Pour le chiffrement version 2, il faut maintenant utiliser une *clé* `k`
  283. à la place de l'entier `n`.
  284. Le script devient:
  285. ```bash
  286. $ python chiffrer2.py k MESSAGE
  287. ```
  288. Pour chiffrer le message, on continue à décaler chaque lettre d'un pas,
  289. mais la valeur du pas n'est plus constante. À la place, elle est
  290. donnée par les lettres de la clé.
  291. Par exemple, avec la clé 'ACB', le pas prend les valeurs `0, 2, 1, 0, 2, 1` etc.
  292. En chiffrant `tintin` avec la clé `ACB`, on doit obtenir `TKOTKO`.
  293. # Casser le chiffrement
  294. Maintenant vous jouez le rôle d'un espion Syldave. Voici ce que vous avez
  295. à votre disposition:
  296. * Le script `chiffrer2.py`
  297. * Le message secret suivant: `IHDXUVZKRISCBNJWBXIDUWVVODUBPRFQRIRGBUR`
  298. Vous savez également que:
  299. * La clé utilisée contient 3 lettres
  300. * Le message parle du maréchal Plekszy-Gladz
  301. Vous devez déchiffrer le message, et obtenir la valeur de la clé.
  302. # Indications - 1
  303. Quelques indices:
  304. * La fonction `ord` permet de convertir une lettre en son code ASCII:
  305. `ord('A') = 65, ord('B') = 66, ... ,ord('Z') = 90`
  306. * La fonction `chr` permet de convertir un entier en lettre:
  307. `chr(65) = 'A', chr(66) = 'B', ..., chr(90) = 'Z'`
  308. # Indications - 2
  309. * L'opérateur `%` permet de s'assurer qu'une valeur est comprise dans un intervalle donné.
  310. `0 % 26 = 0, 1 % 26 = 1, ..., 26 % 26 = 0`
  311. `27 % 26 = 1, 28 % 26 = 2, ...`
  312. * Toutes les chaînes de caractères en Python contiennent les méthodes `is_alpha()` et `upper()`:
  313. `"a".is_alpha() = True, "!".is_alpha() = False`
  314. `"Message Important".upper() = "MESSAGE IMPORTANT"`
  315. # Conseils pour l'implémentation
  316. * Dans `chiffrer.py`, assurez-vous d'avoir une fonction `décale_lettre` prenant une lettre et un pas. Cela facilitera l'implémentation de `chiffrer2.py`.
  317. * Pour la dernière partie:
  318. * Pour casser le message, vous pouvez partir de `chiffrer2.py`. Il y a très peu de code à changer ...
  319. * Il y a $26^3$ clés possibles. Un ordinateur n'aura aucun mal à les essayer toutes une par une (ça ne fait "que" 17 000 possibilités environ)
  320. * Quand vous aurez déchiffré le message, vérifiez que votre clé est correcte, en essayant de le re-chiffrer avec l'algorithme v2 - vous devez retomber sur le message chiffré initial.