Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

index.html 67KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529
  1. <!doctype html>
  2. <html lang=fr>
  3. <head>
  4. <!-- Always define the charset before the title -->
  5. <meta charset=utf-8>
  6. <title>Bonnes pratiques et astuces Python — Biologeek — David Larlet</title>
  7. <!-- Define a viewport to mobile devices to use - telling the browser to assume that the page is as wide as the device (width=device-width) and setting the initial page zoom level to be 1 (initial-scale=1.0) -->
  8. <meta name="viewport" content="width=device-width, initial-scale=1"/>
  9. <!-- Fake favicon, to avoid extra request to the server -->
  10. <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  11. <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
  12. <link rel="manifest" href="/manifest.json">
  13. <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
  14. <noscript>
  15. <style type="text/css">
  16. /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
  17. body {
  18. font-family: 'EquityTextB', serif;
  19. }
  20. h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
  21. font-family: 'EquityCapsB', sans-serif;
  22. font-variant: normal;
  23. }
  24. </style>
  25. </noscript>
  26. <!-- Canonical URL for SEO purposes -->
  27. <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20080511-bonnes-pratiques-et-astuces-python">
  28. </head>
  29. <body>
  30. <div>
  31. <header>
  32. <nav>
  33. <p>
  34. <small>
  35. Je suis <a href="/david/" title="Profil public">David Larlet</a>, <a href="/david/pro/" title="Activité professionnelle">artisan</a> du web qui vous <a href="/david/pro/accompagnement/" title="Activité d’accompagnement">accompagne</a><span class="more-infos"> dans l’acquisition de savoirs pour concevoir des <a href="/david/pro/produits-essentiels/" title="Qu’est-ce qu’un produit essentiel ?">produits essentiels</a></span>. <span class="more-more-infos">Discutons ensemble d’une <a href="/david/pro/devis/" title="En savoir plus">non-demande de devis</a>.</span> Je partage ici mes <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et <a href="/david/correspondances/2017/" title="Lettres hebdomadaires">correspondances</a>.
  36. </small>
  37. </p>
  38. </nav>
  39. </header>
  40. <section>
  41. <h1 property="schema:name">Bonnes pratiques et astuces Python</h1>
  42. <article typeof="schema:BlogPosting">
  43. <div property="schema:articleBody">
  44. <img src="/static/david/biologeek/images/logos/python_nouveau.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
  45. <p>Ça faisait un moment que je n'avais pas parlé des
  46. bonnes pratiques Python mais l'approche de
  47. <a href="http://fr.pycon.org/">Pycon fr</a> (où je présenterai Django :
  48. <a href="http://fr.pycon.org/programme/pourquoi-django/">le pourquoi</a> et
  49. <a href="http://fr.pycon.org/programme/django-au-quotidien-qualite-et-performances/">le comment</a>
  50. le 18 mai), l'événement Python incontournable avec
  51. <a href="http://fr.pycon.org/programme/">un programme des plus alléchants</a>, m'a bien
  52. motivé pour effectuer la traduction de
  53. l'<a href="http://python.net/~goodger/projects/pycon/2007/idiomatic/">une des meilleures présentation</a>
  54. par <a href="http://python.net/~goodger/">David Goodger</a> que je connaisse qui remet
  55. les bonnes pratiques Python à plat, ce qui est toujours bon avant d'aller plus loin.</p>
  56. <h2>La lisibilité est importante</h2>
  57. <blockquote>
  58. <p>Les programmes doivent être écrits pour être lus par des gens et
  59. accidentellement exécutés par les machines.</p>
  60. <p>-- Abelson &amp; Sussman, <em>Structure and Interpretation of Computer Programs</em></p>
  61. </blockquote>
  62. <p>Essayez de rendre vos programmes faciles à lire et évidents.</p>
  63. <h2>PEP 8 : Style Guide pour le code Python</h2>
  64. <p>Une lecture immanquable : <a href="http://www.python.org/dev/peps/pep-0008/">http://www.python.org/dev/peps/pep-0008/</a>
  65. (PEP = Python Enhancement Proposal)</p>
  66. <p>Un PEP est une document procurant des informations à la communauté Python, ou
  67. décrivant une nouvelle fonctionnalité de Python et ses processus ou de son
  68. environnement.</p>
  69. <p>La communauté Python a ses propres standards sur ce à quoi doit ressembler le
  70. code, codifiés dans le PEP8. Ces standards sont différents de ceux des autres
  71. communautés, comme C, Java, etc.</p>
  72. <p>L'indentation et les espaces étant si importants en Python, ce Style Guide est
  73. une standard. Il est important que vous adhériez au guide ! La plupart des
  74. projets suivent ces conventions.</p>
  75. <h2>Whitespace 1</h2>
  76. <ul>
  77. <li>4 espaces par niveau d'indentation.</li>
  78. <li>Pas de tabs.</li>
  79. <li>Ne <strong>jamais</strong> mixer des tabs et des espaces.</li>
  80. <li>Un saut de ligne entre les fonctions.</li>
  81. <li>Deux sauts de ligne entre les classes.</li>
  82. </ul>
  83. <h2>Whitespace 2</h2>
  84. <ul>
  85. <li>Ajoutez un espace après ", ", dans les dictionnaires, les listes, les
  86. tuples, les arguments d'une liste d'arguments et après ":" dans les
  87. dictionnaires mais pas avant.</li>
  88. <li>Mettez des espaces autour des assignements et des comparaisons (excepté
  89. pour les arguments d'une liste).</li>
  90. <li>Pas d'espace aux ouvertures/fermetures de parenthèses ou juste avant une
  91. liste d'arguments.</li>
  92. <li>Pas d'espace en ouverture/fermeture de docstrings.<pre><code>def make_squares(key, value=0):
  93. """Return a dictionary and a list..."""
  94. d = {key: value}
  95. l = [key, value]
  96. return d, l
  97. </code></pre>
  98. </li>
  99. </ul>
  100. <h2>Nommage</h2>
  101. <ul>
  102. <li><code>joined_lower</code> pour les fonctions, méthodes et attributs</li>
  103. <li><code>joined_lower</code> ou <code>ALL_CAPS</code> pour les constantes</li>
  104. <li><code>StudlyCaps</code> pour les classes</li>
  105. <li><code>camelCase</code> <strong>seulement</strong> pour suivre des conventions pré-existantes</li>
  106. <li>Attributs: <code>interface</code>, <code>_internal</code>, <code>__private</code></li>
  107. </ul>
  108. <p>Mais essayez d'éviter la forme <code>__privée</code>. Je ne l'utilise jamais.
  109. Faites moi confiance. Si vous l'utilisez, vous le regretterez plus tard.</p>
  110. <h2>Longues lignes et continuité</h2>
  111. <p>Garder une taille de ligne inférieure à 80 caractères.</p>
  112. <p>Utilisez la continuité implicite des lignes au sein des
  113. parenthèses/crochets/accolades :</p>
  114. <pre><code>def __init__(self, first, second, third,
  115. fourth, fifth, sixth):
  116. output = (first + second + third
  117. + fourth + fifth + sixth)
  118. </code></pre>
  119. <p>Utilisez les backslashs en dernier recours :</p>
  120. <pre><code>VeryLong.left_hand_side \
  121. = even_longer.right_hand_side()
  122. </code></pre>
  123. <p>Les backslashs sont locaux, ils doivent terminer la ligne sur laquelle
  124. ils sont. Si vous ajoutez un espace après le backslash, ça ne sert à rien.
  125. Ah aussi, c'est laid.</p>
  126. <h2>Longues chaînes de caractères</h2>
  127. <p>Les chaînes de caractères adjacentes sont concaténées par le parser:</p>
  128. <pre><code>&gt;&gt;&gt; print 'o' 'n' "e"
  129. one
  130. </code></pre>
  131. <p>Les espaces entre les chaînes ne sont pas requis, mais aident à la
  132. lisibilité. Tous les types de quotes sont utilisable :</p>
  133. <pre><code>&gt;&gt;&gt; print 't' r'\/\/' """o"""
  134. t\/\/o
  135. </code></pre>
  136. <p>La chaîne précédée par "r" est une chaîne de type "raw". Les backslashs
  137. ne sont pas évalués comme étant des caractères d'échappement dans les
  138. chaînes de type raw. Elles sont utiles pour les expressions régulières
  139. et les chemins de fichiers Windows.</p>
  140. <p>Notez que les chaînes de caractères nommées <strong>ne sont pas</strong> concaténées :</p>
  141. <pre><code>&gt;&gt;&gt; a = 'three'
  142. &gt;&gt;&gt; b = 'four'
  143. &gt;&gt;&gt; a b
  144. File "&lt;stdin&gt;", line 1
  145. a b
  146. ^
  147. SyntaxError: invalid syntax
  148. </code></pre>
  149. <p>Cela vient du fait que la concaténation automatique est une fonctionnalité
  150. du parser/compiler Python, pas de l'interpréteur. Vous devez utiliser le
  151. signe "+" pour concaténer des chaînes de caractères à l'éxecution.</p>
  152. <pre><code>text = ('Long strings can be made up '
  153. 'of several shorter strings.')
  154. </code></pre>
  155. <p>Les parenthèses autorisent la continuité implicite des lignes.
  156. Les chaînes de caractères sur plusieurs lignes utilisent les triple quotes :</p>
  157. <pre><code>"""Triple
  158. double
  159. quotes"""
  160. '''\
  161. Triple
  162. single
  163. quotes\
  164. '''
  165. </code></pre>
  166. <p>Dans le dernier exemple ci-dessus (simple triple quotes), notez
  167. l'utilisation du backslash pour échapper les nouvelles lignes. Cela élimine
  168. les nouvelles lignes en conservant les quotes joliment alignées à gauche.
  169. Les backslashs doivent être à la fin de leurs lignes.</p>
  170. <h2>Déclarations</h2>
  171. <p>Bon :</p>
  172. <pre><code>if foo == 'blah':
  173. do_something()
  174. do_one()
  175. do_two()
  176. do_three()
  177. </code></pre>
  178. <p>Mauvais :</p>
  179. <pre><code>if foo == 'blah': do_something()
  180. do_one(); do_two(); do_three()
  181. </code></pre>
  182. <p>Les espaces et l'indentation sont de bons indicateurs visuels du flot du
  183. programme. L'indentation de la seconde ligne du "Bon" ci-dessus montre
  184. au lecteur que quelque chose va se produire, alors que le manque
  185. d'indentation dans le "Mauvais" exemple cache le "if".</p>
  186. <p>Les déclarations multiples sur une même ligne sont une torture.
  187. En Python, <em>la lisibilité compte</em>.</p>
  188. <h2>Docstrings et Commentaires</h2>
  189. <p>Docstrings = <strong>Comment utiliser</strong> le code</p>
  190. <p>Commentaires = <strong>Pourquoi</strong> (rationnel) et <strong>comment le code fonctionne</strong></p>
  191. <p>Les docstrings expliquent <strong>comment</strong> utiliser le code et sont là pour
  192. <strong>les utilisateurs</strong> de votre code. Quelques usages :</p>
  193. <ul>
  194. <li>Expliquer le but d'une fonction même si ça vous semble évident car ça ne
  195. semblera pas forcément évident à une personne plus tard.</li>
  196. <li>Décrire les paramètres attendus, les valeurs retournées et les exceptions
  197. levées.</li>
  198. <li>Si la méthode est fortement couplée à un seul appelant, mentionner
  199. la fonction appelante (attention au fait que celle-ci puisse changer).</li>
  200. </ul>
  201. <p>Les commentaires expliquent <strong>pourquoi</strong> et sont pour les mainteneurs de
  202. votre code. Examples incluant des notes pour vous-même, comme :</p>
  203. <pre><code># !!! BUG: ...
  204. # !!! FIX: This is a hack
  205. # ??? Why is this here?
  206. </code></pre>
  207. <p>Les deux types sont de <strong>votre</strong> ressort donc écrivez de bonnes docstrings
  208. et de bons commentaires !</p>
  209. <p>Les docstrings sont utiles pour un usage interactif (<code>help()</code>) et pour
  210. les systèmes d'auto-documentation.</p>
  211. <p>Les commentaires et docstrings faux sont pire que tout. Donc conservez les
  212. à jour ! Lorsque vous effectuez des modifications, assurez vous que les
  213. commentaires et les docstrings sont cohérents avec le code.</p>
  214. <p>Il y a <a href="http://www.python.org/dev/peps/pep-0257/">un PEP entier consacré aux docstrings, PEP 257, "Docstring
  215. Conventions"</a>.</p>
  216. <h2>La pratique a raison de la théorie</h2>
  217. <p>Il y a toujours des exceptions. Issu du PEP 8 :</p>
  218. <blockquote>
  219. <p>Mais plus important : sachez être pertinents - parfois le style guide ne
  220. s'applique pas. Lorsque vous avez un doute, utilisez votre raison. Étudiez
  221. d'autres possibilités et décidez de ce qui vous semble le mieux.
  222. Et n'hésitez pas à demander !
  223. Deux bonnes raisons de ne pas suivre une règle particulière :</p>
  224. <p>(1) Lorsque appliquer la règle va rendre le code moins lisible, même pour
  225. quelqu'un qui est habitué à lire du code qui suit les règles.</p>
  226. <p>(2) Pour être cohérent avec du code préexistant qui enfreint aussi ces règles
  227. (peut-être pour des raisons historiques) -- même si c'est aussi une opportunité
  228. pour faire un peu de nettoyage (dans un pur style XP).</p>
  229. </blockquote>
  230. <p>... mais la pratique ne doit pas réduire la théorie à néant !</p>
  231. <p>On plonge maintenant au cœur du tutoriel : les astuces. On va commencer avec
  232. les plus faciles et augmenter progressivement le niveau.</p>
  233. <h2>Variables intermédiaires</h2>
  234. <p>Dans les autres langages :</p>
  235. <pre><code>temp = a
  236. a = b
  237. b = temp
  238. </code></pre>
  239. <p>En Python :</p>
  240. <pre><code>b, a = a, b
  241. </code></pre>
  242. <p>Vous l'avez peut-être déjà rencontré mais savez vous comment ça fonctionne ?</p>
  243. <ul>
  244. <li>La <strong>virgule</strong> est la syntaxe de construction du tuple.</li>
  245. <li>Un tuple est créé à droite (tuple packing).</li>
  246. <li>Un tuple en est la cible à gauche (tuple unpacking).</li>
  247. </ul>
  248. <p>La partie à droite est <strong>unpackée</strong> dans les noms de tuple de la partie à
  249. gauche.</p>
  250. <p>D'autres exemples:</p>
  251. <pre><code>&gt;&gt;&gt; l =['David', 'Pythonista', '+1-514-555-1234']
  252. &gt;&gt;&gt; name, title, phone = l
  253. &gt;&gt;&gt; name
  254. 'David'
  255. &gt;&gt;&gt; title
  256. 'Pythonista'
  257. &gt;&gt;&gt; phone
  258. '+1-514-555-1234'
  259. </code></pre>
  260. <p>Utile dans les boucles sur des données structurées (la variable <code>l</code>
  261. ci-dessus a été conservée) :</p>
  262. <pre><code>&gt;&gt;&gt; people = [l, ['Guido', 'BDFL', 'unlisted']]
  263. &gt;&gt;&gt; for (name, title, phone) in people:
  264. ... print name, phone
  265. ...
  266. David +1-514-555-1234
  267. Guido unlisted
  268. </code></pre>
  269. <p>Chaque item de <code>people</code> est unpacké dans le tuple <code>(name, title, phone)</code>.</p>
  270. <p>Il est aussi possible de faire le chemin inverse, il faut juste s'assurer
  271. d'avoir la même structure à droite et à gauche :</p>
  272. <pre><code>&gt;&gt;&gt; david, (gname, gtitle, gphone) = people
  273. &gt;&gt;&gt; gname
  274. 'Guido'
  275. &gt;&gt;&gt; gtitle
  276. 'BDFL'
  277. &gt;&gt;&gt; gphone
  278. 'unlisted'
  279. &gt;&gt;&gt; david
  280. ['David', 'Pythonista', '+1-514-555-1234']
  281. </code></pre>
  282. <h2>Aller plus loin avec les tuples</h2>
  283. <p>On a vu que la <strong>virgule</strong> était le constructeur du tuple, pas les
  284. parenthèses. Par exemple :</p>
  285. <pre><code>&gt;&gt;&gt; 1,
  286. (1,)
  287. </code></pre>
  288. <p>L'interpréteur Python montre les parenthèses pour que ce soit plus clair
  289. et je vous conseille de faire de même :</p>
  290. <pre><code>&gt;&gt;&gt; (1,)
  291. (1,)
  292. </code></pre>
  293. <p>Mais n'oubliez pas la virgule !</p>
  294. <pre><code>&gt;&gt;&gt; (1)
  295. 1
  296. </code></pre>
  297. <p>Dans un tuple contenant un seul élément, la virgule est nécessaire. Dans
  298. un tuple avec plus de 2 éléments, la virgule finale est optionnelle.
  299. Pour un tuple vide, une paire de parenthèses suffit :</p>
  300. <pre><code>&gt;&gt;&gt; ()
  301. ()
  302. &gt;&gt;&gt; tuple()
  303. ()
  304. </code></pre>
  305. <p>Une erreur de typo courante est de laisser une virgule alors que vous ne
  306. souhaitez pas avoir un tuple. Il est très facile de l'oublier dans votre
  307. code :</p>
  308. <pre><code>&gt;&gt;&gt; value = 1,
  309. &gt;&gt;&gt; value
  310. (1,)
  311. </code></pre>
  312. <p>Donc si vous vous retrouvez avec un tuple alors que vous ne vous y
  313. attendiez pas, cherchez la virgule ! (<em>Note du traducteur</em> : de ma propre
  314. expérience, il est plus courant d'oublier la virgule pour un tuple ne
  315. contenant qu'un seul élément, dans les settings de Django par exemple,
  316. cherchez plutôt la virgule manquante dans ces cas là).</p>
  317. <h2>Le "_" interactif</h2>
  318. <p>C'est une fonctionnalité très utile que peu de développeurs connaissent.
  319. (<em>Note du traducteur</em> : bien entendu
  320. <a href="https://larlet.fr/david/biologeek/archives/20060425-python-et-underscore/">vous n'en faites pas partie</a>
  321. et vous connaissez les dangers associés.)</p>
  322. <p>Dans un interpréteur interactif, que vous évaluiez une expression ou que
  323. vous appeliez une fonction, le résultat est stocké dans une variable
  324. temporaire, <code>_</code> (un underscore) :</p>
  325. <pre><code>&gt;&gt;&gt; 1 + 1
  326. 2
  327. &gt;&gt;&gt; _
  328. 2
  329. </code></pre>
  330. <p><code>_</code> stocke la dernière valeur <em>affichée</em>.</p>
  331. <p>Lorsqu'un résultat vaut <code>None</code>, rien n'est affiché, donc <code>_</code> ne change
  332. pas. C'est normal !</p>
  333. <p>Ça ne marche que dans un interpréteur interactif, pas dans un module.</p>
  334. <p>C'est particulièrement utile lorsque vous travaillez sur un problème de
  335. manière interactive, et que vous souhaitez stocker la valeur du dernier
  336. résultat :</p>
  337. <pre><code>&gt;&gt;&gt; import math
  338. &gt;&gt;&gt; math.pi / 3
  339. 1.0471975511965976
  340. &gt;&gt;&gt; angle = _
  341. &gt;&gt;&gt; math.cos(angle)
  342. 0.50000000000000011
  343. &gt;&gt;&gt; _
  344. 0.50000000000000011
  345. </code></pre>
  346. <h2>Construction de chaînes de caractères</h2>
  347. <p>Commençons avec une liste de chaînes de caractères :</p>
  348. <pre><code>colors = ['red', 'blue', 'green', 'yellow']
  349. </code></pre>
  350. <p>On veut concaténer ces chaînes ensemble pour en créer une longue.
  351. Particulièrement lorsque le nombre de sous-chaînes est gros...</p>
  352. <p>Ne faites pas :</p>
  353. <pre><code>result = ''
  354. for s in colors:
  355. result += s
  356. </code></pre>
  357. <p>C'est très lent.
  358. Ça utilise énormément de mémoire et de performances. La somme va additionner,
  359. stocker, et ensuite passer à la suite pour chaque étape intermédiaire.</p>
  360. <p>Faites plutôt ceci :</p>
  361. <pre><code>result = ''.join(colors)
  362. </code></pre>
  363. <p>La méthode <code>join()</code> fait toute la copie en une seule passe.</p>
  364. <p>Lorsque vous ne traitez qu'une petite centaine de chaînes de caractères,
  365. ça ne fait aucune différence. Mais prenez l'habitude de construire vos
  366. chaînes de façon optimale, car avec des milliers ou des boucles, ça <strong>va</strong>
  367. faire la différence.</p>
  368. <h2>Construire des chaînes, solutions 1</h2>
  369. <p>Voici quelques techniques pour utiliser la méthode <code>join()</code>.</p>
  370. <p>Si vous voulez un espace comme séparateur :</p>
  371. <pre><code>result = ' '.join(colors)
  372. </code></pre>
  373. <p>ou une virgule et un espace :</p>
  374. <pre><code>result = ', '.join(colors)
  375. </code></pre>
  376. <p>voici un cas courant d'utilisation :</p>
  377. <pre><code>colors = ['red', 'blue', 'green', 'yellow']
  378. print 'Choose', ', '.join(colors[:-1]), \
  379. 'or', colors[-1]
  380. </code></pre>
  381. <p>Pour faire une phrase grammaticalement correcte, on veut des virgules entre
  382. chaque valeurs sauf la dernière, où l'on préfère un "ou". La syntaxe de
  383. découpage d'une liste s'occupe du reste. La "partie jusqu'à -1" (<code>[:-1]</code>)
  384. retourne tout sauf la dernière valeur, que l'on peut concaténer avec nos
  385. virgules.</p>
  386. <p>Bien sûr, ce code ne fonctionnera pas avec les cas particuliers comme une
  387. liste de taille 0 ou 1. Ce qui retourne :</p>
  388. <pre><code>Choose red, blue, green or yellow
  389. </code></pre>
  390. <h2>Construire des chaînes, solutions 2</h2>
  391. <p>Vous avez besoin d'appliquer une fonction pour générer les chaînes initiales :</p>
  392. <pre><code>result = ''.join(fn(i) for i in items)
  393. </code></pre>
  394. <p>Ça utilise une <em>generator expression</em>, dont on parlera plus tard.</p>
  395. <p>Si vous devez modifier les chaînes de manière incrémentale, commencez par
  396. les stocker dans une liste pour commencer :</p>
  397. <pre><code>items = []
  398. ...
  399. items.append(item) # de nombreuses fois
  400. ...
  401. # une fois la liste complétée
  402. result = ''.join(fn(i) for i in items)
  403. </code></pre>
  404. <p>On accumule les parties de la liste afin de pouvoir appliquer le <code>join</code>,
  405. ce qui est plus rapide.</p>
  406. <h2>Utilisez <code>in</code> lorsque c'est possible (1)</h2>
  407. <p>Bon :</p>
  408. <pre><code>for key in d:
  409. print key
  410. </code></pre>
  411. <ul>
  412. <li><code>in</code> est généralement plus rapide.</li>
  413. <li>Ce pattern marche aussi pour des items dans des containers arbitraires
  414. (comme les listes, les tuples ou les tests).</li>
  415. <li><code>in</code> est aussi un opérateur (comme on va le voir).</li>
  416. </ul>
  417. <p>Mauvais :</p>
  418. <pre><code>for key in d.keys():
  419. print key
  420. </code></pre>
  421. <p>C'est limité aux objects ayant une méthode <code>keys()</code>.</p>
  422. <h2>Utilisez <code>in</code> lorsque c'est possible (2)</h2>
  423. <p>Mais <code>.keys()</code> est <strong>nécessaire</strong> lorsque vous modifiez le dictionnaire :</p>
  424. <pre><code>for key in d.keys():
  425. d[str(key)] = d[key]
  426. </code></pre>
  427. <p><code>d.keys()</code> crée une liste statique des clés du dictionnaire. Sinon, vous
  428. allez lever une exception "RuntimeError: dictionary changed size during iteration".</p>
  429. <p>Utilisez <code>key in dict</code>, et non <code>dict.has_key()</code> :</p>
  430. <pre><code># faites ça :
  431. if key in d:
  432. ...do something with d[key]
  433. # mais pas ça :
  434. if d.has_key(key):
  435. ...do something with d[key]
  436. </code></pre>
  437. <p><code>in</code> est ici utilisé comme un opérateur.</p>
  438. <h2>La méthode <code>get</code> des dictionnaires</h2>
  439. <p>On doit souvent initialiser les entrées d'un dictionnaire avant de les utiliser:</p>
  440. <p>Voici la manière naïve de faire :</p>
  441. <pre><code>navs = {}
  442. for (portfolio, equity, position) in data:
  443. if portfolio not in navs:
  444. navs[portfolio] = 0
  445. navs[portfolio] += position * prices[equity]
  446. </code></pre>
  447. <p><code>dict.get(key, default)</code> permet de ne pas avoir à se soucier du test :</p>
  448. <pre><code>navs = {}
  449. for (portfolio, equity, position) in data:
  450. navs[portfolio] = (navs.get(portfolio, 0)
  451. + position * prices[equity])
  452. </code></pre>
  453. <p>Beaucoup mieux.</p>
  454. <h2>La méthode <code>setdefault</code> des dictionnaires (1)</h2>
  455. <p>Ici on doit initialiser les valeurs d'un dictionnaire mutables. Chaque valeur
  456. du dictionnaire sera une liste. Voici la manière naïve :</p>
  457. <pre><code>equities = {}
  458. for (portfolio, equity) in data:
  459. if portfolio in equities:
  460. equities[portfolio].append(equity)
  461. else:
  462. equities[portfolio] = [equity]
  463. </code></pre>
  464. <p><code>dict.setdefault(key, default)</code> s'occupe de ça de manière beaucoup plus rapide :</p>
  465. <pre><code>equities = {}
  466. for (portfolio, equity) in data:
  467. equities.setdefault(portfolio, []).append(equity)
  468. </code></pre>
  469. <p><code>dict.setdefault()</code> est équivalent à "get ou set &amp; get". Ou
  470. "set si nécessaire, puis get". C'est particulièrement rapide si votre clé de
  471. dictionnaire est coûteuse à générer ou longue à taper.</p>
  472. <p>Le seul problème avec <code>dict.setdefault()</code> c'est que la valeur par défaut est
  473. évaluée, qu'elle soit utilisée ou non. Ça ne pose problème que si la clé est
  474. coûteuse à calculer.</p>
  475. <p>Si la valeur par défaut <strong>est</strong> coûteuse à calculer, vous devriez plutôt
  476. utiliser la classe <code>defaultdict</code>.</p>
  477. <h2>La méthode <code>setdefault</code> des dictionnaires (2)</h2>
  478. <p>On va voir qu'il est possible d'utiliser <code>setdefault</code> pour déclarer une valeur par défaut :</p>
  479. <pre><code>navs = {}
  480. for (portfolio, equity, position) in data:
  481. navs.setdefault(portfolio, 0)
  482. navs[portfolio] += position * prices[equity]
  483. </code></pre>
  484. <p>La méthode <code>setdefault</code> d'un dictionnaire retourne la valeur par défaut, mais
  485. nous l'ignorons ici. On tire profit d'une conséquence de l'utilisation de
  486. <code>setdefault</code>, la valeur n'est initialisée que si elle n'existe pas déjà.</p>
  487. <h2><code>defaultdict</code></h2>
  488. <p>Nouveau avec Python 2.5.</p>
  489. <p><code>defaultdict</code> est nouveau dans Python 2.5, il fait partie du module
  490. <code>collections</code>. <code>defaultdict</code> est identique aux dictionnaires classiques,
  491. excepté pour deux cas :</p>
  492. <ul>
  493. <li>il prend un premier argument optionnel : une fonction factory par défaut</li>
  494. <li>lorsqu'une clé de dictionnaire est rencontrée pour la première fois, la
  495. fonction factory par défaut est appelée et le résultat initialise la
  496. valeur du dictionnaire.</li>
  497. </ul>
  498. <p>Il y a deux manières d'accéder à <code>defaultdict</code> :</p>
  499. <ul>
  500. <li>
  501. <p>importer le module <code>collections</code> et l'appeler à travers le module :</p>
  502. <pre><code>import collections
  503. d = collections.defaultdict(...)
  504. </code></pre>
  505. </li>
  506. <li>
  507. <p>ou importer <code>defaultdict</code> directement :</p>
  508. <pre><code>from collections import defaultdict
  509. d = defaultdict(...)
  510. </code></pre>
  511. </li>
  512. </ul>
  513. <p>Voici l'exemple déjà traité, où chaque valeur du dictionnaire fois être
  514. initialisé pour être une liste vide, réécrit en utilisant <code>defaultdict</code> :</p>
  515. <pre><code>from collections import defaultdict
  516. equities = defaultdict(list)
  517. for (portfolio, equity) in data:
  518. equities[portfolio].append(equity)
  519. </code></pre>
  520. <p>Il n'y a plus d'astuce ici. Dans ce cas, la fonction factory par défaut est
  521. <code>list</code>, ce qui retourne une liste vide.</p>
  522. <p>C'est la manière d'avoir un dictionnaire avec les valeurs par défaut à 0,
  523. utilisez <code>int</code> comme factory :</p>
  524. <pre><code>navs = defaultdict(int)
  525. for (portfolio, equity, position) in data:
  526. navs[portfolio] += position * prices[equity]
  527. </code></pre>
  528. <p>Il faut faire attention à <code>defaultdict</code> quand même. Vous ne pouvez pas
  529. utiliser l'exception <code>KeyError</code> sur un dictionnaire initialisé avec <code>defaultdict</code>.
  530. Vous devez utiliser la condition "key in dict" si vous voulez vérifier
  531. l'existence d'une clé de manière spécifique.</p>
  532. <h2>Construire et scinder des dictionnaires</h2>
  533. <p>Voila une technique utile pour construire un dictionnaire à partir de deux
  534. listes (ou séquences), une liste pour les clés, une liste pour les valeurs :</p>
  535. <pre><code>given = ['John', 'Eric', 'Terry', 'Michael']
  536. family = ['Cleese', 'Idle', 'Gilliam', 'Palin']
  537. pythons = dict(zip(given, family))
  538. &gt;&gt;&gt; pprint.pprint(pythons)
  539. {'John': 'Cleese',
  540. 'Michael': 'Palin',
  541. 'Eric': 'Idle',
  542. 'Terry': 'Gilliam'}
  543. </code></pre>
  544. <p>L'inverse est trivial bien sûr :</p>
  545. <pre><code> &gt;&gt;&gt; pythons.keys()
  546. ['John', 'Michael', 'Eric', 'Terry']
  547. &gt;&gt;&gt; pythons.values()
  548. ['Cleese', 'Palin', 'Idle', 'Gilliam']
  549. </code></pre>
  550. <p>Notez que l'ordre du résultat des .keys() et .values() à est différent des
  551. listes utilisées lors de la création du dictionnaire. L'ordre d'entrée est
  552. différent de l'ordre de sortie car un dictionnaire n'est pas ordonné.
  553. Par contre, l'ordre des clés est consistant avec celui des valeurs, à condition
  554. que le dictionnaire n'ait pas été modifié entre temps.</p>
  555. <h2>Tester des valeurs vraies</h2>
  556. <p>Il est élégant et rapide de tirer partie des avantages de Python en ce qui
  557. concerne les valeurs booléennes :</p>
  558. <pre><code># faites ça : # et pas ça :
  559. if x: if x == True:
  560. pass pass
  561. </code></pre>
  562. <p>Test d'une liste :</p>
  563. <pre><code># faites ça : # et pas ça :
  564. if items: if len(items) != 0:
  565. pass pass
  566. # et surtout pas ça :
  567. if items != []:
  568. pass
  569. </code></pre>
  570. <h2>Valeurs vraies</h2>
  571. <p>Les noms <code>True</code> et <code>False</code> sont des instances intrinsèques à Python de type
  572. <code>bool</code>, des valeurs booléennes. Comme <code>None</code>, il n'existe qu'une seule
  573. instance de chaque.</p>
  574. <table>
  575. <thead>
  576. <tr>
  577. <th>
  578. False
  579. </th>
  580. <th>
  581. True
  582. </th>
  583. </tr>
  584. </thead>
  585. <tbody>
  586. <tr>
  587. <td>
  588. <code>False</code> (== 0)
  589. </td>
  590. <td>
  591. <code>True</code> (== 1)
  592. </td>
  593. </tr>
  594. <tr>
  595. <td>
  596. <code>""</code> (empty string)
  597. </td>
  598. <td>
  599. toutes les chaînes à part <code>""</code> (<code>" "</code>,
  600. <code>"nimportequoi"</code>)
  601. </td>
  602. </tr>
  603. <tr>
  604. <td>
  605. <code>0</code>, <code>0.0</code>
  606. </td>
  607. <td>
  608. n'importe quel chiffre à part <code>0</code>
  609. (1, 0.1, -1, 3.14)
  610. </td>
  611. </tr>
  612. <tr>
  613. <td>
  614. <code>[]</code>, <code>()</code>,
  615. <code>{}</code>, <code>set()</code>
  616. </td>
  617. <td>
  618. n'importe quel container non vide
  619. (<code>[0]</code>, <code>(None,)</code>, <code>['']</code>)
  620. </td>
  621. </tr>
  622. <tr>
  623. <td>
  624. <code>None</code>
  625. </td>
  626. <td>
  627. pratiquement tous les objets qui ne sont
  628. explicitement équivalents à False
  629. </td>
  630. </tr>
  631. </tbody>
  632. </table>
  633. <p>Voici par exemple un objet qui est toujours vrai :</p>
  634. <pre><code>&gt;&gt;&gt; class C:
  635. ... pass
  636. ...
  637. &gt;&gt;&gt; o = C()
  638. &gt;&gt;&gt; bool(o)
  639. True
  640. &gt;&gt;&gt; bool(C)
  641. True
  642. </code></pre>
  643. <p>Pour contrôler la valeur booléenne d'une instance ou d'une classe définie,
  644. utilisez les méthodes spéciales <code>__nonzero__</code> ou <code>__len__</code>. Utilisez
  645. <code>__len__</code> si votre classe est un container qui a une taille :</p>
  646. <pre><code>class MyContainer(object):
  647. def __init__(self, data):
  648. self.data = data
  649. def __len__(self):
  650. """Return my length."""
  651. return len(self.data)
  652. </code></pre>
  653. <p>Si votre classe n'est pas un container, utilisez <code>__nonzero__</code> :</p>
  654. <pre><code>class MyClass(object):
  655. def __init__(self, value):
  656. self.value = value
  657. def __nonzero__(self):
  658. """Return my truth value (True or False)."""
  659. # This could be arbitrarily complex:
  660. return bool(self.value)
  661. </code></pre>
  662. <p>En Python 3.0, <code>__nonzero__</code> a été renommé <code>__bool__</code> afin d'être consistant
  663. avec le type <code>bool</code> natif. Pour être compatible, ajoutez ceci à la définition
  664. de votre classe :</p>
  665. <pre><code>__bool__ = __nonzero__
  666. </code></pre>
  667. <h2>Index &amp; Item (1)</h2>
  668. <p>Voici une manière élégante de vous épargner quelques lignes si vous avez
  669. besoin d'une liste de mots :</p>
  670. <pre><code>&gt;&gt;&gt; items = 'zero one two three'.split()
  671. &gt;&gt;&gt; print items
  672. ['zero', 'one', 'two', 'three']
  673. </code></pre>
  674. <p>Prenons l'exemple d'un itération entre les items d'une liste, pour laquelle
  675. nous voulons à la fois l'item et la position (l'index) de cet item dans la liste :</p>
  676. <pre><code> - ou -
  677. i = 0
  678. for item in items: for i in range(len(items)):
  679. print i, item print i, items[i]
  680. i += 1
  681. </code></pre>
  682. <h2>Index &amp; Item (2): <code>enumerate</code></h2>
  683. <p>La fonction <code>enumerate</code> prend une liste et retourne des paires (index, item) :</p>
  684. <pre><code>&gt;&gt;&gt; print list(enumerate(items))
  685. [(0, 'zero'), (1, 'one'), (2, 'two'), (3, 'three')]
  686. </code></pre>
  687. <p>Il est nécessaire d'avoir recours à une <code>list</code> pour afficher les résultats
  688. car <code>enumerate</code> est une fonction fainéante, générant un item (une paire) à
  689. la fois, seulement lorsqu'il est demandé. Une boucle <code>for</code> nécessite un tel
  690. mécanisme. <code>enumerate</code> est un exemple de <strong>générateur</strong> dont on parlera plus
  691. tard des détails. <code>print</code> ne prend pas un résultat à la fois mais doit être
  692. en possession de la totalité du message à afficher. On a donc converti
  693. automatiquement le générateur en une liste avant d'utiliser print.</p>
  694. <p>Notre boucle devient beaucoup plus simple :</p>
  695. <pre><code>for (index, item) in enumerate(items):
  696. print index, item
  697. # comparé à : # comparé à :
  698. index = 0 for i in range(len(items)):
  699. for item in items: print i, items[i]
  700. print index, item
  701. index += 1
  702. </code></pre>
  703. <p>La version avec <code>enumerate</code> est plus courte et plus simple que la version
  704. de gauche, et plus facile à lire que les deux autres.</p>
  705. <p>Un exemple montrant que la fonction <code>enumerate</code> retourne un itérateur
  706. (un générateur est une sorte d'itérateur) :</p>
  707. <pre><code>&gt;&gt;&gt; enumerate(items)
  708. &lt;enumerate object at 0x011EA1C0&gt;
  709. &gt;&gt;&gt; e = enumerate(items)
  710. &gt;&gt;&gt; e.next()
  711. (0, 'zero')
  712. &gt;&gt;&gt; e.next()
  713. (1, 'one')
  714. &gt;&gt;&gt; e.next()
  715. (2, 'two')
  716. &gt;&gt;&gt; e.next()
  717. (3, 'three')
  718. &gt;&gt;&gt; e.next()
  719. Traceback (most recent call last):
  720. File "&lt;stdin&gt;", line 1, in ?
  721. StopIteration
  722. </code></pre>
  723. <h2>Les autres langages ont des "variables"</h2>
  724. <p>Dans de nombreux autres langages, assigner une variable revient à mettre une
  725. valeur dans une boîte.</p>
  726. <pre><code>int a = 1;
  727. </code></pre>
  728. <p>
  729. <img
  730. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/a1box.png"
  731. alt="Boîte 1 a"
  732. style="margin: 0pt auto; display: block;"/>
  733. </p>
  734. <p>La boîte "a" contient maintenant un integer 1.</p>
  735. <p>Assigner une autre valeur à la même variable remplace le contenu de la boîte :</p>
  736. <pre><code>a = 2;
  737. </code></pre>
  738. <p>
  739. <img
  740. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/a2box.png"
  741. alt="Boîte 2 a"
  742. style="margin: 0pt auto; display: block;"/>
  743. </p>
  744. <p>Maintenant la boîte "a" contient un integer 2.</p>
  745. <p>Assigner une variable à une autre crée une copie de la valeur et la met
  746. dans une nouvelle boîte :</p>
  747. <pre><code>int b = a;
  748. </code></pre>
  749. <p>
  750. <img
  751. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/a2box.png"
  752. alt="Boîte 2 a"
  753. style="margin: 0pt auto; display: block;"/>
  754. </p>
  755. <p>
  756. <img
  757. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/b2box.png"
  758. alt="Boîte 2 b"
  759. style="margin: 0pt auto; display: block;"/>
  760. </p>
  761. <p>"b" est une seconde boîte, avec une copie de l'entier 2. La boîte "a" en a
  762. une copie séparée.</p>
  763. <h2>Python a des "noms"</h2>
  764. <p>En Python, un "nom" ou "identifiant" est comme une étiquette attachée à un
  765. objet.</p>
  766. <pre><code>a = 1
  767. </code></pre>
  768. <p>
  769. <img
  770. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/a1tag.png"
  771. alt="Tag 1 a"
  772. style="margin: 0pt auto; display: block;"/>
  773. </p>
  774. <p>Ici, un objet integer 1 a une étiquette appelée "a".</p>
  775. <p>Si on réassigne "a", on déplace juste l'étiquette sur un autre objet :</p>
  776. <pre><code>a = 2
  777. </code></pre>
  778. <p>
  779. <img
  780. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/a2tag.png"
  781. alt="Tag 2 a"
  782. style="margin: 0pt auto; display: block;"/>
  783. </p>
  784. <p>
  785. <img
  786. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/1.png"
  787. alt="1"
  788. style="margin: 0pt auto; display: block;"/>
  789. </p>
  790. <p>Maintenant le nom "a" est attaché à un objet entier 2.</p>
  791. <p>L'objet entier 1 n'a plus le tag "a". Il peut encore exister mais on n'y a
  792. plus accès via le nom "a". (Lorsqu'un objet n'a plus aucune référence ou
  793. étiquette, il est supprimé de la mémoire.)</p>
  794. <p>Si l'on assigne un nom à un autre, on attache juste une autre étiquette à
  795. un objet existant :</p>
  796. <pre><code>b = a
  797. </code></pre>
  798. <p>
  799. <img
  800. src="/static/david/biologeek/images/python_astuces_bonnes_pratiques/ab2tag.png"
  801. alt="Tag 2 a b"
  802. style="margin: 0pt auto; display: block;"/>
  803. </p>
  804. <p>Le nom "b" est juste une seconde étiquette attachée au même objet que "a".</p>
  805. <p>Bien que l'on réfère communément aux "variables" en Python (car c'est une
  806. terminologie commune aux autres langages), on manipule vraiment de "noms" ou
  807. "identifiants". En Python, les "variables" sont des étiquettes pour des
  808. valeurs, non des boîtes nommés.</p>
  809. <p>Si vous ne comprenez rien au reste de ce tutoriel, j'espère que vous aurez$
  810. au moins retenu la façon dont les noms fonctionnent. Une bonne compréhension
  811. vous permettra d'apprendre rapidement et d'éviter des erreurs comme celle-ci:</p>
  812. <h2>Valeurs de paramètres par défaut</h2>
  813. <p>C'est une erreur courante que les débutants font souvent. Même les
  814. développeurs plus expérimentés la font s'ils n'ont pas compris comment
  815. fonctionnent les noms en Python.</p>
  816. <pre><code>def bad_append(new_item, a_list=[]):
  817. a_list.append(new_item)
  818. return a_list
  819. </code></pre>
  820. <p>Le problème ici c'est que la valeur par défaut <code>a_list</code>, une liste vide,
  821. est évaluée lors de la définition de la fonction. Ainsi à chaque fois que
  822. vous appelez la fonction vous obtenez la <strong>même</strong> valeur par défaut.
  823. Essayez plusieurs fois :</p>
  824. <pre><code>&gt;&gt;&gt; print bad_append('one')
  825. ['one']
  826. &gt;&gt;&gt; print bad_append('two')
  827. ['one', 'two']
  828. </code></pre>
  829. <p>Les listes sont modifiables, vous pouvez modifier leur contenu. La bonne
  830. manière d'avoir une liste par défaut (ou dictionnaire, ou set) est de la
  831. créer au moment du lancement, <strong>au sein de la fonction</strong> :</p>
  832. <pre><code>def good_append(new_item, a_list=None):
  833. if a_list is None:
  834. a_list = []
  835. a_list.append(new_item)
  836. return a_list
  837. </code></pre>
  838. <h2>Formattage des chaînes de caractères avec %</h2>
  839. <p>L'opérateur <code>%</code> fonctionne en Python comme la fonction <code>sprintf</code> de C.</p>
  840. <p>Bien sûr si vous ne connaissez pas C, ça ne vous aide pas. Pour faire simple,
  841. vous définissez un template ou format et des valeurs qui seront interprétées.</p>
  842. <p>Dans cet exemple, le template contient deux spécifications de conversion
  843. "%s" signifie "insérer une chaîne de caractère ici" et "%i" signifie
  844. "convertir un integer en string et l'insérer ici". "%s" est particulièrement
  845. utile car il utilise la fonction standard <code>str()</code> pour convertir un objet
  846. en une chaîne de caractères.</p>
  847. <p>Les valeurs proposées doivent correspondrent au template, on a deux valeurs
  848. ici, un tuple.</p>
  849. <pre><code>name = 'David'
  850. messages = 3
  851. text = ('Hello %s, you have %i messages'
  852. % (name, messages))
  853. print text
  854. </code></pre>
  855. <p>Ce qui donne :</p>
  856. <pre><code>Hello David, you have 3 messages
  857. </code></pre>
  858. <p>Les détails sont dans la <em>Python Library Reference</em>, section 2.3.6.2,
  859. "String Formatting Operations". Mettez cette page en favoris !</p>
  860. <p>Si vous ne l'avez pas encore fait, allez sur python.org, téléchargez la
  861. documentation en HTML (dans un .zip ou une archive), et installez la sur
  862. votre machine. Il n'y a rien de mieux que d'avoir la ressource de référence
  863. à portée de clavier.</p>
  864. <h2>Formattage des chaînes de caractères avancé</h2>
  865. <p>Pourquoi est-ce qu'il y a autant de personnes qui ne réalisent pas qu'il y
  866. a d'autres façons de formater les chaînes de caractères qui peuvent s'avérer
  867. plus puissantes ?</p>
  868. <p>Avec des noms grâce à un dictionnaire :</p>
  869. <pre><code>values = {'name': name, 'messages': messages}
  870. print ('Hello %(name)s, you have %(messages)i '
  871. 'messages' % values)
  872. </code></pre>
  873. <p>Ici on a spécifié les noms des valeurs interprétées, qui constituent les
  874. clés du dictionnaire.</p>
  875. <p>Vous trouvez qu'il y a de la redondance ? Les noms "name" et "messages"
  876. sont déjà définis localement. On peut en tirer parti.</p>
  877. <p>En utilisant les variables locales :</p>
  878. <pre><code>print ('Hello %(name)s, you have %(messages)i '
  879. 'messages' % locals())
  880. </code></pre>
  881. <p>La fonction <code>locals()</code> retourne un dictionnaire de toutes les variables
  882. locales disponibles.</p>
  883. <p>C'est très puissant. Grâce à ça, vous pouvez formater toutes les chaînes de
  884. caractères que vous voulez sans avoir à vous soucier de la correspondance
  885. positionnelle avec les valeurs soumises en argument.</p>
  886. <p>Mais le pouvoir peut être dangereux. ("With great power comes great
  887. responsibility.") Si vous utilisez <code>locals()</code> avec un template issu d'une
  888. ressource externe, vous exposez l'intégralité de votre espace de noms local.
  889. C'est une chose à garder en tête.</p>
  890. <p>Pour examiner votre espace de nom local :</p>
  891. <pre><code>&gt;&gt;&gt; from pprint import pprint
  892. &gt;&gt;&gt; pprint(locals())
  893. </code></pre>
  894. <p><code>pprint</code> est un module très utile. Si vous ne le connaissiez pas déjà,
  895. essayez de jouer avec. Ça rend le debugging des données structurées beaucoup
  896. plus simple !</p>
  897. <h2>Formattage des chaînes de caractères avancé</h2>
  898. <p>L'espace de nom des attributs d'une instance d'objet est simplement un
  899. dictionnaire, <code>self.__dict__</code>.</p>
  900. <p>En utilisant l'espace de nom d'une instance :</p>
  901. <pre><code>print ("We found %(error_count)d errors"
  902. % self.__dict__)
  903. </code></pre>
  904. <p>Equivalent à, mais moins flexible que :</p>
  905. <pre><code>print ("We found %d errors"
  906. % self.error_count)
  907. </code></pre>
  908. <p>Note: Les attributs d'une classe sont dans le <code>__dict__</code> de la classe.
  909. Les espaces de noms sont hérités et constituent donc des dictionnaires
  910. chaînés.</p>
  911. <h2>List Comprehensions</h2>
  912. <p>Les list comprehensions ("listcomps" pour les intimes) sont des raccourcis
  913. syntaxiques pour ce pattern généralement utilisé.</p>
  914. <p>La manière traditionnelle avec <code>for</code> et <code>if</code> :</p>
  915. <pre><code>new_list = []
  916. for item in a_list:
  917. if condition(item):
  918. new_list.append(fn(item))
  919. </code></pre>
  920. <p>En utilisant une list comprehension :</p>
  921. <pre><code>new_list = [fn(item) for item in a_list
  922. if condition(item)]
  923. </code></pre>
  924. <p>Les listcomps sont claires et concises, directes. Vous pouvez avoir plusieurs
  925. boucles <code>for</code> et conditions <code>if</code> au sein d'une même listcomp, mais
  926. au-delà de deux ou trois, ou si les conditions sont complexes, je vous
  927. suggère d'utiliser l'habituelle boucle <code>for</code>. En appliquant le Zen de Python,
  928. utilisez la méthode la plus lisible.</p>
  929. <p>Par exemple, la liste des carrés de 0 à 9 :</p>
  930. <pre><code>&gt;&gt;&gt; [n ** 2 for n in range(10)]
  931. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  932. </code></pre>
  933. <p>La liste des nombres impairs au sein de la précédente liste :</p>
  934. <pre><code>&gt;&gt;&gt; [n ** 2 for n in range(10) if n % 2]
  935. [1, 9, 25, 49, 81]
  936. </code></pre>
  937. <h2>Generator Expressions (1)</h2>
  938. <p>Faisons la somme des carrés des nombres inférieurs à 100 :</p>
  939. <p>Avec une boucle :</p>
  940. <pre><code>total = 0
  941. for num in range(1, 101):
  942. total += num * num
  943. </code></pre>
  944. <p>On peut aussi utiliser la fonction <code>sum</code> qui fait plus rapidement le
  945. travail pour nous en construisant la bonne séquence.</p>
  946. <p>Avec une list comprehension :</p>
  947. <pre><code>total = sum([num * num for num in range(1, 101)])
  948. </code></pre>
  949. <p>Avec une generator expression :</p>
  950. <pre><code>total = sum(num * num for num in xrange(1, 101))
  951. </code></pre>
  952. <p>Les generator expressions ("genexps") sont comme les list
  953. comprehensions, excepté dans leur calcul, les genexps sont fainéantes.
  954. Les listcomps calculent l'intégralité du résultat en une seule passe, pour
  955. le stocker dans une liste. Les generator expressions calculent une valeur à
  956. la fois, lorsqu'elle est nécessaire. C'est particulièrement utile lorsque la
  957. séquence est très longue lorsque la liste générée n'est qu'une étape
  958. intermédiaire et non le résultat final.</p>
  959. <p>Dans ce cas, on est uniquement intéressé par la somme, on n'a pas besoin de
  960. la liste des résultats intermédiaires. On utilise <code>xrange</code> pour la même
  961. raison, ça génère les valeurs une par une.</p>
  962. <h2>Generator Expressions (2)</h2>
  963. <p>Par exemple si on doit faire la somme des carrés de plusieurs milliards
  964. d'entiers, on va arriver à une saturation de la mémoire avec une list
  965. comprehension, mais les generator expressions ne vont avoir aucun problème.
  966. Bon ça va prendre un certain temps par contre !</p>
  967. <pre><code>total = sum(num * num
  968. for num in xrange(1, 1000000000))
  969. </code></pre>
  970. <p>La différence de syntaxe est que les listcomps ont des crochets, alors que
  971. les genexps n'en ont pas. Les generator expressions nécessitent parfois des
  972. parenthèses par contre, vous devriez donc toujours les utiliser.</p>
  973. <p>En bref :</p>
  974. <ul>
  975. <li>Utilisez une list comprehension lorsque le résultat escompté est la liste.</li>
  976. <li>Utilisez une generator expression lorsque la liste n'est qu'un résultat
  977. intermédiaire.</li>
  978. </ul>
  979. <p>Voici un récent exemple de ce que j'ai vu au boulot.</p>
  980. <p>On avait besoin d'un dictionnaire qui corresponde aux chiffres des mois (à
  981. la fois via des chaînes de caractères et via des integers) au code des mois
  982. pour un client. Cela peut être fait avec une ligne de code.</p>
  983. <p>Ça fonctionne de la manière suivante :</p>
  984. <ul>
  985. <li>La fonction de référence <code>dict()</code> prend en argument une liste de paires
  986. de clés/valeurs (2-tuples).</li>
  987. <li>On a une liste des codes des mois (chaque code est une simple lettre, et
  988. une chaîne de caractères est aussi une simple liste de lettres). On parcours
  989. cette liste pour obtenir à la fois le code du mois et l'index.</li>
  990. <li>Le nombre des mois commence à 1 mais Python commence l'indexation à 0,
  991. le nombre des mois correspond dont à index+1.</li>
  992. <li>On veut avoir la correspondance à la fois avec les nombres et les chaînes
  993. de caractères. On peut utiliser les fonctions <code>int()</code> et <code>str()</code> pour
  994. ça et itérer dessus.</li>
  995. </ul>
  996. <p>L'exemple en question :</p>
  997. <pre><code> month_codes = dict((fn(i+1), code)
  998. for i, code in enumerate('FGHJKMNQUVXZ')
  999. for fn in (int, str))
  1000. </code></pre>
  1001. <p>Le résultat obtenu pour <code>month_codes</code> :</p>
  1002. <pre><code>{ 1: 'F', 2: 'G', 3: 'H', 4: 'J', ...
  1003. '1': 'F', '2': 'G', '3': 'H', '4': 'J', ...}
  1004. </code></pre>
  1005. <h2>Ordonner</h2>
  1006. <p>Il est très simple d'ordonner une liste en Python :</p>
  1007. <pre><code>a_list.sort()
  1008. </code></pre>
  1009. <p>(Notez que la liste est ordonnée sur place, la liste originale est ordonnée
  1010. et la fonction <code>sort</code> <strong>ne retourne pas</strong> une liste ou une copie.)</p>
  1011. <p>Mais que faire lorsque vous avec une liste de données à ordonner, mais
  1012. quelle ne s'ordonne pas de manière naturelle ? Par exemple ordonner selon
  1013. la première colonne, puis la quatrième.</p>
  1014. <p>On peut utiliser la fonction de référence <code>sort</code> avec une méthode définie
  1015. par nos soins :</p>
  1016. <pre><code>def custom_cmp(item1, item2):
  1017. returm cmp((item1[1], item1[3]),
  1018. (item2[1], item2[3]))
  1019. a_list.sort(custom_cmp)
  1020. </code></pre>
  1021. <p>Ça marche, mais c'est extrêmement lent pour les listes énormes.</p>
  1022. <h2>Ordonner avec DSU</h2>
  1023. <p>DSU = Decorate-Sort-Undecorate</p>
  1024. <p>Note: DSU n'est bien souvent plus nécessaire, cf. section suivante.</p>
  1025. <p>Au lieu de créer une fonction de comparaison personnalisée, on crée une
  1026. liste intermédiaire qui va pourvoir être ordonnée naturellement :</p>
  1027. <pre><code># Decorate:
  1028. to_sort = [(item[1], item[3], item)
  1029. for item in a_list]
  1030. # Sort:
  1031. to_sort.sort()
  1032. # Undecorate:
  1033. a_list = [item[-1] for item in to_sort]
  1034. </code></pre>
  1035. <p>La première ligne crée une liste contenant des tuples, une copie de la valeur
  1036. à ordonner en premier argument, suivi de la valeur complète de la liste.</p>
  1037. <p>La seconde ligne ordonne grâce à la fonction Python, ce qui est très rapide.</p>
  1038. <p>La troisième ligne récupère la <strong>dernière</strong> valeur de la liste une fois
  1039. ordonnée. Souvenez-vous, cette dernière valeur correspond à l'item complet.
  1040. On n'utilise plus la partie ayant permis d'ordonner, elle a joué son rôle
  1041. et n'est plus utile.</p>
  1042. <p>C'est un compromis espace mémoire + complexité vs. temps. Plus simple et
  1043. rapide mais on est obligé de dupliquer la liste originale.</p>
  1044. <h2>Ordonner avec keys</h2>
  1045. <p>Python 2.4 a introduit un nouvel argument à la méthode <code>sort</code> des listes,
  1046. "key", qui permet de spécifier une fonction à un argument qui est utilisée
  1047. pour comparer chaque élément d'une liste avec les autres. Par exemple :</p>
  1048. <pre><code>def my_key(item):
  1049. return (item[1], item[3])
  1050. to_sort.sort(key=my_key)
  1051. </code></pre>
  1052. <p>La fonction <code>my_key</code> va être appelée une fois par item de la liste <code>to_sort</code>.</p>
  1053. <p>Vous pouvez utiliser votre propre fonction ou utiliser une fonction existante
  1054. qui ne prend qu'un seul argument :</p>
  1055. <ul>
  1056. <li><code>str.lower</code> pour ordonner alphabétiquement sans tenir compte de la casse.</li>
  1057. <li><code>len</code> pour ordonner selon la taille des items (chaînes de caractères ou containers).</li>
  1058. <li><code>int</code> ou <code>float</code> pour ordonner numériquement avec des valeurs qui sont
  1059. des chaînes de caractères comme "2", "123", "35".</li>
  1060. </ul>
  1061. <h2>Generators</h2>
  1062. <p>On a déjà vu les generator expressions. On peut créer nos propres generators,
  1063. comme des fonctions :</p>
  1064. <pre><code>def my_range_generator(stop):
  1065. value = 0
  1066. while value &lt; stop:
  1067. yield value
  1068. value += 1
  1069. for i in my_range_generator(10):
  1070. do_something(i)
  1071. </code></pre>
  1072. <p>Le mot-clé <code>yield</code> transforme une fonction en generator. Lorsque vous
  1073. appelez une fonction generator, au lieu d'exécuter le code directement,
  1074. Python retourne un objet generator, qui est un itérateur. Il a une méthode
  1075. <code>next</code>. Les boucles <code>for</code> appellent la méthode <code>next</code> de l'itérateur,
  1076. jusqu'à ce qu'une exception du type <code>StopIteration</code> soit levée.
  1077. Vous pouvez lever l'exception <code>StopIteration</code> explicitement ou de manière
  1078. implicite comme dans le code ci-dessous.</p>
  1079. <p>Les générateurs peuvent simplifier la manière de gérer les
  1080. séquences/itérateurs, car on n'a pas besoin de créer des listes
  1081. intermédiaires. Ça ne génère qu'une valeur à la fois.</p>
  1082. <p>Voici comment la boucle <code>for</code> fonctionne réellement. Python analyse la
  1083. séquence déclarée avec le mot-clé <code>in</code>. Si c'est un simple container (comme
  1084. une liste, un tuple, un dictionnaire, un set ou un container défini par
  1085. l'utilisateur) Python le converti en itérateur. Si c'est déjà un itérateur,
  1086. Python ne fait rien.</p>
  1087. <p>Python appelle ensuite de manière itérative la méthode <code>next</code> de
  1088. l'itérateur, assignant la valeur retournée au compteur de la boucle (<code>i</code>
  1089. dans notre cas), et exécute le code indenté. C'est répété, encore et encore
  1090. jusqu'à ce que <code>StopIteration</code> soit levée, ou qu'un <code>break</code> soit exécuté.</p>
  1091. <p>Une boucle <code>for</code> peut être dotée d'un <code>else</code>, au sein de laquelle le
  1092. code est exécuté si rien ne s'est produit dans la boucle for, mais <strong>non</strong>
  1093. après un <code>break</code>. Cette distinction permet de faire des choses élégantes.
  1094. <code>else</code> est rarement utilisé avec la boucle <code>for</code> mais peut s'avérer
  1095. très puissant lorsque la logique correspond à ce que vous souhaitez faire.</p>
  1096. <p>Par exemple, si on doit vérifier qu'une condition est toujours remplie par
  1097. tous les items d'une liste :</p>
  1098. <pre><code>for item in sequence:
  1099. if condition(item):
  1100. break
  1101. else:
  1102. raise Exception('Condition not satisfied.')
  1103. </code></pre>
  1104. <h2>Exemple de generator</h2>
  1105. <p>Filtrer les colonnes vides à partir d'un fichier CSV (ou des items d'une liste) :</p>
  1106. <pre><code>def filter_rows(row_iterator):
  1107. for row in row_iterator:
  1108. if row:
  1109. yield row
  1110. data_file = open(path, 'rb')
  1111. irows = filter_rows(csv.reader(data_file))
  1112. </code></pre>
  1113. <h2>Lire les lignes d'un fichier de données</h2>
  1114. <pre><code>datafile = open('datafile')
  1115. for line in datafile:
  1116. do_something(line)
  1117. </code></pre>
  1118. <p>C'est possible car les fichiers sont dotés d'une méthode <code>next</code>, comme
  1119. d'autres itérateurs : les listes, les tuples, les dictionnaires (pour leurs
  1120. clés), les generators.</p>
  1121. <p>Il y a un piège ici : étant donnée la façon dont sont mises en cache les
  1122. données, vous ne pouvez pas utiliser à la fois les méthodes <code>.next</code> et
  1123. <code>.read*</code> à moins que vous n'utilisez Python 2.5+.</p>
  1124. <h2>EAFP vs. LBYL</h2>
  1125. <p>Il est plus facile de demander le pardon que la permission (EAFP) vs. analyser
  1126. avant d'échouer (LBYL). Généralement EAFP est préféré, mais pas toujours.</p>
  1127. <ul>
  1128. <li>Duck typing
  1129. Si ça marche comme un canard, parle comme un canard et ressemble à un
  1130. canard : c'est un canard.</li>
  1131. <li>Exceptions
  1132. Essayez de forcer le type si un objet doit être d'un type particulier.
  1133. Si <code>x</code> doit être une chaîne de caractères pour que votre code
  1134. fonctionne, pourquoi ne pas appeler <code>str(x)</code> au lieu d'essayer quelque`
  1135. chose comme <code>isinstance(x, str)</code>.</li>
  1136. </ul>
  1137. <h2>Exemple EAFP <code>try/except</code></h2>
  1138. <p>Vous pouvez encapsuler vos exceptions dans un bloc <code>try/except</code> pour
  1139. pour récupérer les erreurs et vous allez probablement arriver à une solution
  1140. qui est beaucoup plus générale que si vous aviez essayer d'anticiper chaque
  1141. cas.</p>
  1142. <pre><code>try:
  1143. return str(x)
  1144. except TypeError:
  1145. ...
  1146. </code></pre>
  1147. <p>Note: Spécifiez toujours l'exception à attraper. N'utilisez jamais
  1148. <code>except</code> tout seul. Sinon <code>except</code> va cacher d'autres exceptions qui
  1149. risquent d'être levées rendant votre code très difficile à debugger.</p>
  1150. <h2>Importer</h2>
  1151. <pre><code>from module import *
  1152. </code></pre>
  1153. <p>Vous avez probablement déjà vu cette manière de faires des imports avec une
  1154. "étoile". Vous l'appréciez peut-être. <strong>Ne l'utilisez pas.</strong></p>
  1155. <p>Pour paraphraser un exemple très connu :</p>
  1156. <blockquote>
  1157. <p>LUKE: Est-ce que <code>from module import *</code> est meilleur que des imports explicites ?
  1158. YODA: Non, pas meilleur. Plus rapide, plus simple, plus séduisant.
  1159. LUKE: Mais comment saurais-je pourquoi les imports explicites sont meilleurs que les formes étoilées ?
  1160. YODA: Tu sauras lorsque ton code dans 6 mois tu essayeras de lire.</p>
  1161. </blockquote>
  1162. <p>Les imports étoilés sont le mauvais côté de la Force en Python.</p>
  1163. <p>Les imports de type <code>from module import *</code> polluent votre espace de nom.
  1164. Vous allez avoir des choses que vous n'attendiez pas. Vous pouvez avoir des
  1165. conflits avec les noms que vous avez défini localement. Vous n'allez plus
  1166. savoir d'où viennent certains noms. Bien que ce soit un raccourci pratique,
  1167. ça ne doit pas arriver en production.</p>
  1168. <p>Morale : <strong>n'utilisez pas d'imports étoilés !</strong></p>
  1169. <p>Il est bien meilleur de référencer les noms à partir de leurs modules :</p>
  1170. <pre><code>import module
  1171. module.name
  1172. </code></pre>
  1173. <p>importer un module avec un nom plus court si nécessaire (avec <code>alias</code>) :</p>
  1174. <pre><code>import long_module_name as mod
  1175. mod.name
  1176. </code></pre>
  1177. <p>ou importer juste les noms dont vous avez besoin de manière explicite :</p>
  1178. <pre><code>from module import name
  1179. name
  1180. </code></pre>
  1181. <p>Notez qu'il est nécessaire d'utiliser "reload()" sur un module lorsque vous
  1182. utilisez le prompt interactif si vous éditez celui-ci.</p>
  1183. <h2>Modules et scripts</h2>
  1184. <p>Pour faire à la fois un module importable et un script exécutable :</p>
  1185. <pre><code>if __name__ == '__main__':
  1186. # script code here
  1187. </code></pre>
  1188. <p>Lorsqu'il est importé, un attribut<code>__name__</code> est setté, correspondant au
  1189. nom du fichier du module, sans ".py". Le code ci-dessus ne va donc pas être
  1190. lancé lors d'un import. Lorsqu'il est lancé comme un script, l'attribut
  1191. <code>__name__</code> est setté à "<strong>main</strong>" et le script va être exécuté.</p>
  1192. <p>Excepté pour certains cas spéciaux, vous ne devriez placer aucun code
  1193. important au plus haut niveau. Placez votre code dans des fonctions, classes,
  1194. méthodes et protégez le avec <code>if __name__ == '__main__'</code>.</p>
  1195. <h2>Structure d'un module</h2>
  1196. <pre><code>"""module docstring"""
  1197. # imports
  1198. # constants
  1199. # exception classes
  1200. # interface functions
  1201. # classes
  1202. # internal functions &amp; classes
  1203. def main(...):
  1204. ...
  1205. if __name__ == '__main__':
  1206. status = main()
  1207. sys.exit(status)
  1208. </code></pre>
  1209. <p>C'est la façon dont un module devrait être structuré.</p>
  1210. <h2>Utilisation de la ligne de commande</h2>
  1211. <p>Exemple (<em>Note du traducteur</em> : <a href="https://larlet.fr/david/biologeek/archives/2006218-un-template-python-pour-parser-des-arguments/">j'ai déjà parlé de ça aussi</a>) :</p>
  1212. <pre><code>#!/usr/bin/env python
  1213. """
  1214. Module docstring.
  1215. """
  1216. import sys
  1217. import optparse
  1218. def process_command_line(argv):
  1219. """
  1220. Return a 2-tuple: (settings object, args list).
  1221. `argv` is a list of arguments, or `None` for ``sys.argv[1:]``.
  1222. """
  1223. if argv is None:
  1224. argv = sys.argv[1:]
  1225. # initialize the parser object:
  1226. parser = optparse.OptionParser(
  1227. formatter=optparse.TitledHelpFormatter(width=78),
  1228. add_help_option=None)
  1229. # define options here:
  1230. parser.add_option( # customized description; put --help last
  1231. '-h', '--help', action='help',
  1232. help='Show this help message and exit.')
  1233. settings, args = parser.parse_args(argv)
  1234. # check number of arguments, verify values, etc.:
  1235. if args:
  1236. parser.error('program takes no command-line arguments; '
  1237. '"%s" ignored.' % (args,))
  1238. # further process settings &amp; args if necessary
  1239. return settings, args
  1240. def main(argv=None):
  1241. settings, args = process_command_line(argv)
  1242. # application code here, like:
  1243. # run(settings, args)
  1244. return 0 # success
  1245. if __name__ == '__main__':
  1246. status = main()
  1247. sys.exit(status)
  1248. </code></pre>
  1249. <h2>Packages</h2>
  1250. <pre><code>package/
  1251. __init__.py
  1252. module1.py
  1253. subpackage/
  1254. __init__.py
  1255. module2.py
  1256. </code></pre>
  1257. <ul>
  1258. <li>Utilisés pour organiser un projet.</li>
  1259. <li>Réduisent le nombre d'entrées lors du chargement.</li>
  1260. <li>Réduisent les conflits en cas d'imports.</li>
  1261. </ul>
  1262. <p>Exemple :</p>
  1263. <pre><code>import package.module1
  1264. from package.subpackage import module2
  1265. from package.subpackage.module2 import name
  1266. </code></pre>
  1267. <p>En Python 2.5 on a maintenant les imports absolus et relatifs via un import
  1268. du futur :</p>
  1269. <pre><code>from __future__ import absolute_import
  1270. </code></pre>
  1271. <p>Je n'ai pas encore eu l'occasion de tester ça moi-même, on va donc couper
  1272. court à toute discussion à ce sujet.</p>
  1273. <h2>Simple is Better Than Complex</h2>
  1274. <blockquote>
  1275. <p>Débugger est deux fois plus difficile que d'écrire du code en premier jet.
  1276. De plus, si vous écrivez le code aussi intelligemment que possible, vous
  1277. êtes, par définition, pas assez intelligent pour le débugger.</p>
  1278. <p>-- Brian W. Kernighan, co-auteur de <em>The C Programming Language</em>
  1279. et le "K" dans "AWK"</p>
  1280. </blockquote>
  1281. <p>En d'autres termes, gardez vos programmes simples !</p>
  1282. <h2>Ne réinventez pas la roue</h2>
  1283. <p>Avant d'écrire une seule ligne de code,</p>
  1284. <ul>
  1285. <li>Vérifiez que cela n'est pas dans la bibliothèque standard de Python.</li>
  1286. <li>Vérifiez que cela n'est pas dans le <a href="http://cheeseshop.python.org/pypi">Python Package Index</a> (the "Cheese Shop")</li>
  1287. <li>Cherchez sur le web. <em>Google is your friend.</em></li>
  1288. </ul>
  1289. <h2>Retour du traducteur</h2>
  1290. <p>Pour terminer, et si vous souhaitez aller plus loin, une
  1291. <a href="http://www.dabeaz.com/generators/">excellente présentation sur les générateurs</a>
  1292. que je n'aurais malheureusement pas le temps de traduire permet d'envisager la
  1293. programmation Python d'une manière tout à fait différente. Elle est orientée
  1294. administration système mais elle peut vraiment être appliquée à de nombreux cas.
  1295. Et si vous voulez comprendre l'intérêt des décorateurs,
  1296. <a href="http://avinashv.net/2008/04/python-decorators-syntactic-sugar/">un bon exemple</a>
  1297. vaut mieux que tous les discours. Mangez du Python, c'est bon pour la santé !</p>
  1298. </div>
  1299. </article>
  1300. <footer>
  1301. <h6 property="schema:datePublished">— 11/05/2008</h6>
  1302. </footer>
  1303. </section>
  1304. <section>
  1305. <div>
  1306. <h3>Articles peut-être en rapport</h3>
  1307. <ul>
  1308. <li><a href="/david/biologeek/archives/20080211-astuces-et-bonnes-pratiques-django/" title="Accès à ★ Astuces et bonnes pratiques Django">★ Astuces et bonnes pratiques Django</a></li>
  1309. <li><a href="/david/biologeek/archives/20070519-presentation-de-django-aux-journees-python-francophones/" title="Accès à Présentation de Django aux journées Python francophones">Présentation de Django aux journées Python francophones</a></li>
  1310. <li><a href="/david/biologeek/archives/20060505-pourquoi-programmer-en-python/" title="Accès à ★ Pourquoi programmer en Python ?">★ Pourquoi programmer en Python ?</a></li>
  1311. </ul>
  1312. </div>
  1313. </section>
  1314. <section>
  1315. <div id="comments">
  1316. <h3>Commentaires</h3>
  1317. <div class="comment" typeof="schema:UserComments">
  1318. <p class="comment-meta">
  1319. <span class="comment-author" property="schema:creator">Gilles</span> le <span class="comment-date" property="schema:commentTime">11/05/2008</span> :
  1320. </p>
  1321. <div class="comment-content" property="schema:commentText">
  1322. <p>Salut David,</p>
  1323. <p>Merci pour cette traduction :) Mémo très utile.</p>
  1324. <p>Bonne soirée.</p>
  1325. </div>
  1326. </div>
  1327. <div class="comment" typeof="schema:UserComments">
  1328. <p class="comment-meta">
  1329. <span class="comment-author" property="schema:creator">Oncle Tom</span> le <span class="comment-date" property="schema:commentTime">11/05/2008</span> :
  1330. </p>
  1331. <div class="comment-content" property="schema:commentText">
  1332. <p>Tip-top cet article. On aurait presque pu croire que c&#39;est toi qui l&#39;avait écrit ;-)</p>
  1333. </div>
  1334. </div>
  1335. <div class="comment" typeof="schema:UserComments">
  1336. <p class="comment-meta">
  1337. <span class="comment-author" property="schema:creator">NiKo</span> le <span class="comment-date" property="schema:commentTime">11/05/2008</span> :
  1338. </p>
  1339. <div class="comment-content" property="schema:commentText">
  1340. <p>Je trouve ça dommage de demander à contraindre les lignes à 80 caractères tout en demandant 4 espaces comme intervalle d&#39;indentation, ça fait perdre pas mal d&#39;espace. Perso j&#39;aime bien 2 espaces, je ne trouve pas que cela rendre le code illisible pour autant.</p>
  1341. </div>
  1342. </div>
  1343. <div class="comment" typeof="schema:UserComments">
  1344. <p class="comment-meta">
  1345. <span class="comment-author" property="schema:creator">Thesa</span> le <span class="comment-date" property="schema:commentTime">12/05/2008</span> :
  1346. </p>
  1347. <div class="comment-content" property="schema:commentText">
  1348. <p>Super traduction ! Un billet à conserver dans un coin, ça sera utile !</p>
  1349. <p>Merci :-)</p>
  1350. </div>
  1351. </div>
  1352. <div class="comment" typeof="schema:UserComments">
  1353. <p class="comment-meta">
  1354. <span class="comment-author" property="schema:creator">thibault</span> le <span class="comment-date" property="schema:commentTime">12/05/2008</span> :
  1355. </p>
  1356. <div class="comment-content" property="schema:commentText">
  1357. <p>L&#39;éternelle guerre entre les espaces et les tabulations. Perso, je ne comprends vraiment pas l&#39;intérêt d&#39;indenter à coup d&#39;espaces, mais bon... (troll inside)</p>
  1358. </div>
  1359. </div>
  1360. <div class="comment" typeof="schema:UserComments">
  1361. <p class="comment-meta">
  1362. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">14/05/2008</span> :
  1363. </p>
  1364. <div class="comment-content" property="schema:commentText">
  1365. <p>Merci pour vos encouragements, c&#39;était tellement loooooong que ça fait plaisir ;-).</p>
  1366. <p>@NiKo : perso j&#39;utilise 4 espaces pour la lisibilité mais je ne m&#39;impose pas absolument de rester sous les 80 lignes, ça dépend des cas. Je sais plus où Guido disait : corporate == 2 espaces, autre == 4 espaces.</p>
  1367. <p>@thibault : il n&#39;y a pas de guerre, c&#39;est surtout un problème d&#39;éditeurs qui finissent par mixer les deux et là c&#39;est mal. Dans l&#39;idéal il faudrait utiliser des tabs pour laisser la liberté à l&#39;utilisateur de configurer la largeur de tab qui lui plait (2 ou 4 espaces), dans la pratique il vaut mieux imposer les espaces (les bons éditeurs font ça).</p>
  1368. </div>
  1369. </div>
  1370. <div class="comment" typeof="schema:UserComments">
  1371. <p class="comment-meta">
  1372. <span class="comment-author" property="schema:creator">Fabien</span> le <span class="comment-date" property="schema:commentTime">14/05/2008</span> :
  1373. </p>
  1374. <div class="comment-content" property="schema:commentText">
  1375. <p>Ce qui est intéressant de faire, c&#39;est de mettre un hook svn en pre-commit, pour vérifier le coding style avec le script pep8.py (et en profiter pour utiliser d&#39;autres logiciels ... pyflakes &amp; co).</p>
  1376. </div>
  1377. </div>
  1378. <div class="comment" typeof="schema:UserComments">
  1379. <p class="comment-meta">
  1380. <span class="comment-author" property="schema:creator">Ikipou</span> le <span class="comment-date" property="schema:commentTime">15/05/2008</span> :
  1381. </p>
  1382. <div class="comment-content" property="schema:commentText">
  1383. <p>Excellent article.</p>
  1384. <p>Est-ce que tu le publies sous licence libre? J&#39;aimerais beaucoup le republier sur le site <a href="http://OpenYourCode.org">http://OpenYourCode.org</a> dans la partie Python.</p>
  1385. </div>
  1386. </div>
  1387. <div class="comment" typeof="schema:UserComments">
  1388. <p class="comment-meta">
  1389. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">15/05/2008</span> :
  1390. </p>
  1391. <div class="comment-content" property="schema:commentText">
  1392. <p>C&#39;est du CC BY-SA originellement donc vas-y fais toi plaisir :-).</p>
  1393. </div>
  1394. </div>
  1395. <div class="comment" typeof="schema:UserComments">
  1396. <p class="comment-meta">
  1397. <span class="comment-author" property="schema:creator">Frédéric Péters</span> le <span class="comment-date" property="schema:commentTime">08/06/2008</span> :
  1398. </p>
  1399. <div class="comment-content" property="schema:commentText">
  1400. <p>Très utile traduction; une petite erreur dans « La liste des nombres premiers au sein de la précédente liste »; il s&#39;agit de la liste des nombres impairs, pas des nombres premiers.</p>
  1401. </div>
  1402. </div>
  1403. <div class="comment" typeof="schema:UserComments">
  1404. <p class="comment-meta">
  1405. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">09/06/2008</span> :
  1406. </p>
  1407. <div class="comment-content" property="schema:commentText">
  1408. <p>@Frédéric Péters : merci c&#39;est corrigé.</p>
  1409. </div>
  1410. </div>
  1411. <div class="comment" typeof="schema:UserComments">
  1412. <p class="comment-meta">
  1413. <span class="comment-author" property="schema:creator">loupblanc</span> le <span class="comment-date" property="schema:commentTime">09/07/2008</span> :
  1414. </p>
  1415. <div class="comment-content" property="schema:commentText">
  1416. <p>Merci beaucoup pour cette excellente traduction !</p>
  1417. </div>
  1418. </div>
  1419. <div class="comment" typeof="schema:UserComments">
  1420. <p class="comment-meta">
  1421. <span class="comment-author" property="schema:creator">radada</span> le <span class="comment-date" property="schema:commentTime">28/11/2008</span> :
  1422. </p>
  1423. <div class="comment-content" property="schema:commentText">
  1424. <p>Merci ! Plein d&#39;infos enfin claires et compréhensibles ! Juste une toute petite erreur je crois dans l&#39;explication sur les package : choisir entre &#39;package&#39; et &#39;packages&#39; ;)</p>
  1425. </div>
  1426. </div>
  1427. <div class="comment" typeof="schema:UserComments">
  1428. <p class="comment-meta">
  1429. <span class="comment-author" property="schema:creator">tarball</span> le <span class="comment-date" property="schema:commentTime">20/03/2009</span> :
  1430. </p>
  1431. <div class="comment-content" property="schema:commentText">
  1432. <p>Salut David,</p>
  1433. <p>dans ta rubrique &quot;GENERATOR EXPRESSIONS (2)&quot;, à la fin, n&#39;aurait-il pas été plus pertinent d&#39;écrire :</p>
  1434. <p>month_codes = dict(map(lambda(x,y):(x + 1,y), enumerate(&#39;FGHJKMNQUVXZ&#39;)))</p>
  1435. <p>qui est quand même plus simple et plus direct ?</p>
  1436. <p>merci pour ce mémo, excellent travail ! ;-)</p>
  1437. </div>
  1438. </div>
  1439. <div class="comment" typeof="schema:UserComments">
  1440. <p class="comment-meta">
  1441. <span class="comment-author" property="schema:creator">experts CMS django</span> le <span class="comment-date" property="schema:commentTime">01/03/2011</span> :
  1442. </p>
  1443. <div class="comment-content" property="schema:commentText">
  1444. <p>L&#39;année 2011 s&#39;annonce chargée pour les éditeurs de CMS. Les principales solutions du marché viennent toutes de proposer en quelques semaines une nouvelle version de leur outil. Après Django</p>
  1445. </div>
  1446. </div>
  1447. </div>
  1448. </section>
  1449. <footer>
  1450. <nav>
  1451. <p>
  1452. <small>
  1453. Je réponds quasiment toujours aux <a href="m&#x61;ilto:d&#x61;vid%40l&#x61;rlet&#46;fr" title="Envoyer un email">emails</a> (<a href="/david/signature/" title="Ma signature actuelle avec possibilité de chiffrement">signés</a>) et vous pouvez me rencontrer à Montréal. <span class="more-infos">N’hésitez pas à <a href="/david/log/" title="Être tenu informé des mises à jour">vous abonner</a> pour être tenu informé des publications récentes.</span>
  1454. </small>
  1455. </p>
  1456. </nav>
  1457. </footer>
  1458. </div>
  1459. <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
  1460. <script data-no-instant>InstantClick.init()</script>
  1461. </body>
  1462. </html>