Imported Upstream version 12.1.0
[contrib/python-twisted.git] / doc / historic / 2003 / europython / doanddont.html
1 <html><head><title>Idioms and Anti-Idioms in Python</title></head><body>
2
3 <h1>Idioms and Anti-Idioms in Python</h1>
4
5 <h2>Idioms and Anti-Idioms, AKA Do and Don't</h2><ul>
6 <li>Welcome</li>
7
8 <li>Gimmick -- Charmed quotes</li>
9
10 </ul>
11 <hr />
12 <em>Prue (Something Wicca This Way Comes, season 1) -- No, we are not supposed to use our powers</em>
13 <h2>Python</h2><ul>
14 <li>Few gotchas...</li>
15
16 <li>...but not zero</li>
17
18 <li>Most are easy to avoid...</li>
19
20 <li>...if you know about them.</li>
21
22 </ul>
23 <hr />
24 <em>Prue (Something Wicca This Way Comes, season 1) -- Uh, it doesn't work out there either.</em>
25 <h2>Exceptions</h2><ul>
26 <li>Primary method of dealing with errors</li>
27
28 <li>Flexible</li>
29
30 <li>Good opportunity to shoot yourself in foot...</li>
31
32 <li>...without knowing about it (bug only shows up rarely.)</li>
33
34 </ul>
35 <hr />
36 <em>Leo (Paige From the Past, season 4) -- You have to [...] Paige. No exceptions.</em>
37 <h2>Exceptions -- Catching Too Much</h2><ul>
38 <li>Classical case: 'except:'</li>
39
40 <li>Will catch anything</li>
41
42 <li>Including most bugs...<ul><li>NameError, AttributeError...</li>
43 </ul></li>
44
45 </ul>
46 <hr />
47 <em>Piper (Charmed Again, season 4) -- Okay, well this is way too much for me to handle. </em>
48 <h2>Exceptions -- Catching Too Much -- Example</h2>
49 <pre class="python">
50 try:
51    f = opne("file")
52 except:
53    sys.exit("no such file")
54 </pre>
55
56 <hr />
57 <em>Piper (Charmed Again, season 4) -- Way too much.</em>
58 <h2>Exceptions -- Catching Too Soon</h2><ul>
59 <li>The slogan:<ul><li>Don't catch errors you can do nothing about</li>
60 </ul></li>
61
62 <li>Catching exceptions should by the 'user'</li>
63
64 <li>The point where the value is *used*<ul><li>Rather than passed on</li>
65 </ul></li>
66
67 </ul>
68 <hr />
69 <em>Phoebe (Knight to Remember, season 4) -- Maybe it's just too soon.</em>
70 <h2>Exceptions -- Catching Too Soon -- Example</h2>
71 <pre class="python">
72 def readlinesfromfile(file):
73     try:
74         return open(file).readlines()
75     except IOError:
76         pass # do what?
77 </pre>
78 <ul><li>What can we do?<ul><li>Return empty list? bad</li>
79
80 <li>Print warning? what if it's one of several possibilities</li>
81
82 <li>Exit? NO!</li>
83
84 <li>Raise our own exception? Losing information</li>
85 </ul></li>
86
87 </ul>
88 <hr />
89 <em>Paige (Knight to Remember, season 4) -- I'm already a little late.</em>
90 <h2>Catching multiple exceptions</h2><ul>
91 <li>Spot bug here:</li></ul>
92
93 <pre class="python">
94 try:
95    fp = open("file")
96 except IOError, OSError:
97    print "could not open file"
98 </pre>
99 <hr />
100 <em>Paige (Knight to Remember, season 4) -- Because I've got too many responsibilities</em>
101 <h2>Catching multiple exceptions (cont'd)</h2><ul>
102 <li>Bug:</li>
103
104 <li>Only IOError gets caught...</li>
105
106 <li>and exception value is put in OSError</li>
107
108 <li>But most exceptions are IOError :(</li>
109
110 <li>Likely to not discover this bug</li>
111
112 </ul>
113 <hr />
114 <em>Piper (Knight to Remember, season 4) -- Alright! Calm down!</em>
115 <h2>Catching multiple exceptions (cont'd 2)</h2><ul>
116 <li>Correct way</li></ul>
117
118 <pre class="python">
119 try:
120    fp = open("file")
121 except (IOError, OSError):
122    print "could not open file"
123 </pre>
124 <hr />
125 <em>Phoebe (Knight to Remember, season 4) -- Besides that, maybe we can help</em>
126 <h2>Catching NameError</h2>
127
128 <pre class="python">
129 try:
130    import foo
131 except ImportError:
132    pass
133
134 try:
135    foo.Function()
136 except NameError:
137    pass # some replacement
138 </pre>
139 <ul><li>Bad idea!</li>
140
141 </ul>
142 <hr />
143 <em>Piper (Morality Bites, season 4) -- That's OK, I forgot your name too.</em>
144 <h2>Catching NameError (cont'd)</h2>
145
146 <pre class="python">
147 try:
148    import foo
149 except ImportError:
150    foo = None
151
152 if foo is not None:
153    foo.Function()
154 else:
155    pass # some replacement
156 </pre>
157 <ul><li>If foo.Function() sometimes has a NameError, we won't mask it...</li>
158
159 <li>...or if we misspell 'foo'</li>
160
161 </ul>
162 <hr />
163 <em>Anne (Morality Bites, season 4) -- Oh, right, sorry.</em>
164 <h2>Importing Modules -- A Review</h2><ul>
165 <li>'import module'</li>
166
167 <li>'from module import name1, name2'</li>
168
169 <li>Only imports once (or does it?)</li>
170
171 </ul>
172 <hr />
173 <em>Phoebe (Animal Pragmatism, season 2) -- Rome was not built in a day,</em>
174 <h2>Importing __main__</h2><ul>
175 <li>__main__ is where the 'script' is executed</li>
176
177 <li>Avoid the temptation to import __main__</li>
178
179 <li>Put common function in a named module</li>
180
181 <li>Then your code will be more useful</li>
182
183 </ul>
184 <hr />
185 <em>Piper (Animal Pragmatism, season 2) -- And why mess with a good thing?</em>
186 <h2>Importing a File Twice</h2><ul>
187 <li>But it can't be, can it?</li>
188
189 <li>Importing a script into itself</li></ul>
190
191 <pre class="python">
192 # file: hello.py
193 import hello
194 class Foo: pass
195 </pre>
196 <ul><li>Two 'Foo's, same definition, different class!</li>
197
198 <li>If your sys.path includes packages...</li>
199
200 <li>...you can import a module once from a package and once plain</li>
201
202 </ul>
203 <hr />
204 <em>Phoebe (Which Prue Is It, Anyway?, season 1) -- Okay, which one of you is the real Prue?</em>
205 <h2>Importing *</h2><ul>
206 <li>Don't do it<ul><li>Don't do it</li>
207 </ul></li>
208
209 <li>Classic mistake:</li></ul>
210
211 <pre class="python">
212 from os import *
213
214 fp = open("file") # works
215 fp.readline() # fails with a weird error...?
216 </pre>
217 <ul><li>os.open returns a file descriptor (number)</li>
218
219 </ul>
220 <hr />
221 <em>Pink Prue (Which Prue Is It, Anyway?, season 1) -- So, um, what did I do now?</em>
222 <h2>Importing * Inside Functions</h2><ul>
223 <li>Just invalid Python...</li>
224
225 <li>...but happens to work in 1.5.2...</li>
226
227 <li>...and sometimes in 2.1...</li>
228
229 <li>...never in 2.2.</li>
230
231 <li>Just Say No</li>
232
233 </ul>
234 <hr />
235 <em>Pink Prue (Which Prue Is It, Anyway?, season 1) -- What ever it is, I have an alibi.</em>
236 <h2>Importing Names</h2><ul>
237 <li>from foo import name1, name2</li>
238
239 <li>Not a bad idea always</li>
240
241 <li>But be careful of repercussions:</li>
242
243 <li>modules sometimes change things inside</li>
244
245 <li>You won't see those changes</li>
246
247 <li>Opportunity for inconsistency!</li>
248
249 </ul>
250 <hr />
251 <em>Real Prue (Which Prue Is It, Anyway?, season 1) -- Because I still have to work here when all of this is over.</em>
252 <h2>Reloading</h2><ul>
253 <li>reload(module) -- reread module from file</li>
254
255 <li>Useful in long running processes?</li>
256
257 <li>Doesn't play nice with 'from import name'</li>
258
259 <li>Beware of exceptions: the new classes are different from old classes</li>
260
261 </ul>
262 <hr />
263 <em>Real Prue (Which Prue Is It, Anyway?, season 1) -- Don't worry I'm never casting that spell again.</em>
264 <h2>exec, execfile and eval</h2><ul>
265 <li>Execute arbitrary Python code</li>
266
267 <li>No-cost scripting language for applications</li>
268
269 <li>But easy to shoot one's self in the foot</li>
270
271 </ul>
272 <hr />
273 <em>Reporter (Morality Bites, season 2) -- More news on the execution of Phoebe Halliwell coming up.</em>
274 <h2>exec, execfile and eval -- Modify namespaces</h2><ul>
275 <li>They modify the namespace they're in<ul><li>...but not always.</li>
276 </ul></li>
277
278 <li>Depends on global vs. inside functions</li>
279
280 <li>Use with care -- or with explicit dictionaries</li>
281
282 </ul>
283 <hr />
284 <em>Nathaniel (Morality Bites, season 2) -- Executions are a bitch to plan.</em>
285 <h2>exec, execfile and eval -- Inside functions</h2><ul>
286 <li>Unadorned exec is invalid inside functions</li>
287
288 <li>execfile and eval play badly with local var. optimisation</li>
289
290 <li>Always use with explicit dictionary</li>
291
292 </ul>
293 <hr />
294 <em>Nathaniel (Morality Bites, season 2) -- Phoebe, what is this? An attempt to stay your execution?</em>
295 <h2>Conclusion: recommended usage</h2><ul>
296 <li>d={};exec "code" in d</li>
297
298 <li>d={};execfile("file", d)</li>
299
300 <li>d={};eval("expression", d)</li>
301
302 <li>Sometimes useful to pre-populate dictionary</li>
303
304 </ul>
305 <hr />
306 <em>Phoebe (Morality Bites, season 2) -- Just because you don't understand something, doesn't make it evil.</em>
307 <h2>exec, execfile and eval -- Restricted Execution (Don't)</h2><ul>
308 <li>rexec never was audited</li>
309
310 <li>History of holes</li>
311
312 <li>Dangerous to allow arbitrary code</li>
313
314 <li>DoS attacks not defended against at all</li>
315
316 <li>Recursion</li>
317
318 </ul>
319 <hr />
320 <em>Leo (Morality Bites, season 2) -- Nobody's gonna rescue you.</em>
321 <h2>Syntax</h2><ul>
322 <li>Python syntax regular and nice...</li>
323
324 <li>...but not perfect.</li>
325
326 <li>Some care needed.</li>
327
328 </ul>
329 <hr />
330 <em>Prue (Morality Bites, season 2) -- You know, we can still make the good things happen.</em>
331 <h2>Syntax -- Tabs and Spaces</h2><ul>
332 <li>Use Tabs</li>
333
334 <li>Or use spaces</li>
335
336 <li>But don't mix them...</li>
337
338 <li>...ever!</li>
339
340 <li>Invites bugs</li>
341
342 </ul>
343 <hr />
344 <em>Prue (The Painted World, season 2) -- We've seen so many bizarre things.</em>
345 <h2>Syntax -- Backslash Continuations</h2>
346
347 <pre class="python">
348 # Extra newline
349 r = 1 \
350
351 +2
352
353 # Missing backslash in long series
354 r = 1 \
355 +2 \
356 +3 \
357 +4 
358 +5 \
359 +6
360 </pre>
361 <ul><li>Both *silently* do the wrong things</li></ul>
362
363 <h2>Syntax -- Backslash Continuations (cont'd)</h2>
364
365 <ul><li>Better</li></ul>
366
367 <pre class="python">
368 # Extra newline
369 r = (1
370
371 +2)
372
373 # Long series
374 r = (1
375 +2
376 +3
377 +4
378 +5
379 +6)
380 </pre>
381
382 <hr />
383 <em>Prue (The Painted World, season 2) -- Uh, what just happened here?</em>
384 <h2>Hand Hacking Batteries</h2><ul>
385 <li>Don't write os.path functions yourself<ul><li>os.path.join especially</li>
386 </ul></li>
387
388 <li>min, max</li>
389
390 <li>urlparse</li>
391
392 <li>Skim through modules list. A lot.</li>
393
394 </ul>
395 <hr />
396 <em>Prue (Animal Pragmatism, season 2) -- Well, we didn't find anything in the Book Of Shadows.</em>
397 <h2>Further Reading</h2><ul>
398 <li><a href="http://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/howtos/doanddont/doanddont.html">http://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/howtos/doanddont/doanddont.html</a></li>
399
400 <li><a href="http://www.amk.ca/python/writing/warts.html">http://www.amk.ca/python/writing/warts.html</a></li>
401
402 <li><a href="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</a></li>
403
404 </ul>
405 <hr />
406 <em>Phoebe (The Painted World, season 2) -- I think you'll find me pretty knowledgeable about all areas</em>
407 <h2>Questions?</h2>
408 <em>Piper (The Painted World, season 2) -- You're like ask rainman.com</em>
409
410 <h2>Bonus Slides</h2>
411 <em>Phoebe (The Painted World, season 2) -- Oh, and P.S. there will be no personal gain.</em>
412
413 <h2>Packages and __init__.py</h2><ul>
414 <li>Packages are determined by __init__.py files</li>
415
416 <li>Temptation to put code in __init__.py</li>
417
418 <li>But two namespaces mix: __init__'s and filesystem's</li>
419
420 <li>Put comments, docstring and __all__</li>
421
422 </ul>
423 <hr />
424 <em>Piper (Animal Pragmatism, season 2) -- It's a package. One I would like to share with you.</em>
425 <h2>Type Checking</h2><ul>
426 <li>Python's typing is highly dynamic</li>
427
428 <li>Capability-based, not class-based</li>
429
430 <li>Explicit type checks hurt code usefulness</li>
431
432 <li>(common use -- proxies, for testing)</li>
433
434 </ul>
435 <hr />
436 <em>Phoebe (Black as Cole, season 2) -- I never thought of myself as the marrying type</em>
437 <h2>Type Checking -- Example</h2><ul>
438 <li>Here's what not to do:</li></ul>
439
440 <pre class="python">
441 class Foo:
442     def __init__(self, i):
443         if type(i) is types.StringType:
444             self.content = open(i).readlines()
445         elif type(i) is types.ListType:
446             self.content = i
447 </pre>
448 <ul><li>(inspired from a question on #python)</li>
449
450 <li>More badness than you can shake a stick at.</li>
451
452 </ul>
453 <hr />
454 <em>Phoebe (Muse to My Ears, season 4) -- You're an artistic, creative type.</em>
455 <h2>Type Checking -- Example -- Fixed</h2>
456 <pre class="python">
457
458 class Foo:
459     pass
460
461 class FooFromFile(Foo):
462
463     def __init__(self, filename):
464          self.content = open(filename).readlines()
465
466 class FooFromList(Foo):
467
468     def __init__(self, list):
469          self.content = list
470 </pre>
471
472 <hr />
473 <em>Phoebe (Muse to My Ears, season 4) -- You see how well this worked out?</em>
474 <h2>Private __Attributes</h2><ul>
475 <li>Useful in deep hierarchies to keep attributes separate</li>
476
477 <li>Mangle only class name -- *not* module name</li>
478
479 <li>Makes it harder to test</li>
480
481 <li>Makes it harder to hand-hack for debugging</li>
482
483 </ul>
484 <hr />
485 <em>Tessa (Animal Pragmatism, season 2) -- Maybe it's our fault because we tried to make them into something they're not.</em>
486
487 <h2>Using Mutable Default Arguments</h2>
488
489 <pre class="python">
490 def foo(l=[]):
491     l.append(5);return l
492 </pre>
493
494 <ul>
495 <li>Will modify the same list.</li>
496 <li>If you want that -- use object, class, not that hack.</li>
497 </ul>
498
499 <pre class="python">
500 def foo(l=None):
501     if l is None: l=[]
502     l.append(5);return l
503 </pre>
504 <hr />
505 <em>Snake guy (Animal Pragmatism, season 2) --
506 You two are acting like nothing's changed.</em>
507
508 </body></html>