1 <html><head><title>Idioms and Anti-Idioms in Python</title></head><body>
3 <h1>Idioms and Anti-Idioms in Python</h1>
5 <h2>Idioms and Anti-Idioms, AKA Do and Don't</h2><ul>
8 <li>Gimmick -- Charmed quotes</li>
12 <em>Prue (Something Wicca This Way Comes, season 1) -- No, we are not supposed to use our powers</em>
14 <li>Few gotchas...</li>
16 <li>...but not zero</li>
18 <li>Most are easy to avoid...</li>
20 <li>...if you know about them.</li>
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>
30 <li>Good opportunity to shoot yourself in foot...</li>
32 <li>...without knowing about it (bug only shows up rarely.)</li>
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>
40 <li>Will catch anything</li>
42 <li>Including most bugs...<ul><li>NameError, AttributeError...</li>
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>
53 sys.exit("no such file")
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>
62 <li>Catching exceptions should by the 'user'</li>
64 <li>The point where the value is *used*<ul><li>Rather than passed on</li>
69 <em>Phoebe (Knight to Remember, season 4) -- Maybe it's just too soon.</em>
70 <h2>Exceptions -- Catching Too Soon -- Example</h2>
72 def readlinesfromfile(file):
74 return open(file).readlines()
78 <ul><li>What can we do?<ul><li>Return empty list? bad</li>
80 <li>Print warning? what if it's one of several possibilities</li>
84 <li>Raise our own exception? Losing information</li>
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>
96 except IOError, OSError:
97 print "could not open file"
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>
104 <li>Only IOError gets caught...</li>
106 <li>and exception value is put in OSError</li>
108 <li>But most exceptions are IOError :(</li>
110 <li>Likely to not discover this bug</li>
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>
121 except (IOError, OSError):
122 print "could not open file"
125 <em>Phoebe (Knight to Remember, season 4) -- Besides that, maybe we can help</em>
126 <h2>Catching NameError</h2>
137 pass # some replacement
139 <ul><li>Bad idea!</li>
143 <em>Piper (Morality Bites, season 4) -- That's OK, I forgot your name too.</em>
144 <h2>Catching NameError (cont'd)</h2>
155 pass # some replacement
157 <ul><li>If foo.Function() sometimes has a NameError, we won't mask it...</li>
159 <li>...or if we misspell 'foo'</li>
163 <em>Anne (Morality Bites, season 4) -- Oh, right, sorry.</em>
164 <h2>Importing Modules -- A Review</h2><ul>
165 <li>'import module'</li>
167 <li>'from module import name1, name2'</li>
169 <li>Only imports once (or does it?)</li>
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>
177 <li>Avoid the temptation to import __main__</li>
179 <li>Put common function in a named module</li>
181 <li>Then your code will be more useful</li>
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>
189 <li>Importing a script into itself</li></ul>
196 <ul><li>Two 'Foo's, same definition, different class!</li>
198 <li>If your sys.path includes packages...</li>
200 <li>...you can import a module once from a package and once plain</li>
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>
209 <li>Classic mistake:</li></ul>
214 fp = open("file") # works
215 fp.readline() # fails with a weird error...?
217 <ul><li>os.open returns a file descriptor (number)</li>
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>
225 <li>...but happens to work in 1.5.2...</li>
227 <li>...and sometimes in 2.1...</li>
229 <li>...never in 2.2.</li>
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>
239 <li>Not a bad idea always</li>
241 <li>But be careful of repercussions:</li>
243 <li>modules sometimes change things inside</li>
245 <li>You won't see those changes</li>
247 <li>Opportunity for inconsistency!</li>
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>
255 <li>Useful in long running processes?</li>
257 <li>Doesn't play nice with 'from import name'</li>
259 <li>Beware of exceptions: the new classes are different from old classes</li>
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>
267 <li>No-cost scripting language for applications</li>
269 <li>But easy to shoot one's self in the foot</li>
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>
278 <li>Depends on global vs. inside functions</li>
280 <li>Use with care -- or with explicit dictionaries</li>
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>
288 <li>execfile and eval play badly with local var. optimisation</li>
290 <li>Always use with explicit dictionary</li>
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>
298 <li>d={};execfile("file", d)</li>
300 <li>d={};eval("expression", d)</li>
302 <li>Sometimes useful to pre-populate dictionary</li>
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>
310 <li>History of holes</li>
312 <li>Dangerous to allow arbitrary code</li>
314 <li>DoS attacks not defended against at all</li>
320 <em>Leo (Morality Bites, season 2) -- Nobody's gonna rescue you.</em>
322 <li>Python syntax regular and nice...</li>
324 <li>...but not perfect.</li>
326 <li>Some care needed.</li>
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>
334 <li>Or use spaces</li>
336 <li>But don't mix them...</li>
340 <li>Invites bugs</li>
344 <em>Prue (The Painted World, season 2) -- We've seen so many bizarre things.</em>
345 <h2>Syntax -- Backslash Continuations</h2>
353 # Missing backslash in long series
361 <ul><li>Both *silently* do the wrong things</li></ul>
363 <h2>Syntax -- Backslash Continuations (cont'd)</h2>
365 <ul><li>Better</li></ul>
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>
392 <li>Skim through modules list. A lot.</li>
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>
400 <li><a href="http://www.amk.ca/python/writing/warts.html">http://www.amk.ca/python/writing/warts.html</a></li>
402 <li><a href="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</a></li>
406 <em>Phoebe (The Painted World, season 2) -- I think you'll find me pretty knowledgeable about all areas</em>
408 <em>Piper (The Painted World, season 2) -- You're like ask rainman.com</em>
410 <h2>Bonus Slides</h2>
411 <em>Phoebe (The Painted World, season 2) -- Oh, and P.S. there will be no personal gain.</em>
413 <h2>Packages and __init__.py</h2><ul>
414 <li>Packages are determined by __init__.py files</li>
416 <li>Temptation to put code in __init__.py</li>
418 <li>But two namespaces mix: __init__'s and filesystem's</li>
420 <li>Put comments, docstring and __all__</li>
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>
428 <li>Capability-based, not class-based</li>
430 <li>Explicit type checks hurt code usefulness</li>
432 <li>(common use -- proxies, for testing)</li>
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>
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:
448 <ul><li>(inspired from a question on #python)</li>
450 <li>More badness than you can shake a stick at.</li>
454 <em>Phoebe (Muse to My Ears, season 4) -- You're an artistic, creative type.</em>
455 <h2>Type Checking -- Example -- Fixed</h2>
461 class FooFromFile(Foo):
463 def __init__(self, filename):
464 self.content = open(filename).readlines()
466 class FooFromList(Foo):
468 def __init__(self, list):
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>
477 <li>Mangle only class name -- *not* module name</li>
479 <li>Makes it harder to test</li>
481 <li>Makes it harder to hand-hack for debugging</li>
485 <em>Tessa (Animal Pragmatism, season 2) -- Maybe it's our fault because we tried to make them into something they're not.</em>
487 <h2>Using Mutable Default Arguments</h2>
495 <li>Will modify the same list.</li>
496 <li>If you want that -- use object, class, not that hack.</li>
505 <em>Snake guy (Animal Pragmatism, season 2) --
506 You two are acting like nothing's changed.</em>