doanddont.html   [plain text]


<html><head><title>Idioms and Anti-Idioms in Python</title></head><body>

<h1>Idioms and Anti-Idioms in Python</h1>

<h2>Idioms and Anti-Idioms, AKA Do and Don't</h2><ul>
<li>Welcome</li>

<li>Gimmick -- Charmed quotes</li>

</ul>
<hr />
<em>Prue (Something Wicca This Way Comes, season 1) -- No, we are not supposed to use our powers</em>
<h2>Python</h2><ul>
<li>Few gotchas...</li>

<li>...but not zero</li>

<li>Most are easy to avoid...</li>

<li>...if you know about them.</li>

</ul>
<hr />
<em>Prue (Something Wicca This Way Comes, season 1) -- Uh, it doesn't work out there either.</em>
<h2>Exceptions</h2><ul>
<li>Primary method of dealing with errors</li>

<li>Flexible</li>

<li>Good opportunity to shoot yourself in foot...</li>

<li>...without knowing about it (bug only shows up rarely.)</li>

</ul>
<hr />
<em>Leo (Paige From the Past, season 4) -- You have to [...] Paige. No exceptions.</em>
<h2>Exceptions -- Catching Too Much</h2><ul>
<li>Classical case: 'except:'</li>

<li>Will catch anything</li>

<li>Including most bugs...<ul><li>NameError, AttributeError...</li>
</ul></li>

</ul>
<hr />
<em>Piper (Charmed Again, season 4) -- Okay, well this is way too much for me to handle. </em>
<h2>Exceptions -- Catching Too Much -- Example</h2>
<pre class="python">
try:
   f = opne("file")
except:
   sys.exit("no such file")
</pre>

<hr />
<em>Piper (Charmed Again, season 4) -- Way too much.</em>
<h2>Exceptions -- Catching Too Soon</h2><ul>
<li>The slogan:<ul><li>Don't catch errors you can do nothing about</li>
</ul></li>

<li>Catching exceptions should by the 'user'</li>

<li>The point where the value is *used*<ul><li>Rather than passed on</li>
</ul></li>

</ul>
<hr />
<em>Phoebe (Knight to Remember, season 4) -- Maybe it's just too soon.</em>
<h2>Exceptions -- Catching Too Soon -- Example</h2>
<pre class="python">
def readlinesfromfile(file):
    try:
        return open(file).readlines()
    except IOError:
        pass # do what?
</pre>
<ul><li>What can we do?<ul><li>Return empty list? bad</li>

<li>Print warning? what if it's one of several possibilities</li>

<li>Exit? NO!</li>

<li>Raise our own exception? Losing information</li>
</ul></li>

</ul>
<hr />
<em>Paige (Knight to Remember, season 4) -- I'm already a little late.</em>
<h2>Catching multiple exceptions</h2><ul>
<li>Spot bug here:</li></ul>

<pre class="python">
try:
   fp = open("file")
except IOError, OSError:
   print "could not open file"
</pre>
<hr />
<em>Paige (Knight to Remember, season 4) -- Because I've got too many responsibilities</em>
<h2>Catching multiple exceptions (cont'd)</h2><ul>
<li>Bug:</li>

<li>Only IOError gets caught...</li>

<li>and exception value is put in OSError</li>

<li>But most exceptions are IOError :(</li>

<li>Likely to not discover this bug</li>

</ul>
<hr />
<em>Piper (Knight to Remember, season 4) -- Alright! Calm down!</em>
<h2>Catching multiple exceptions (cont'd 2)</h2><ul>
<li>Correct way</li></ul>

<pre class="python">
try:
   fp = open("file")
except (IOError, OSError):
   print "could not open file"
</pre>
<hr />
<em>Phoebe (Knight to Remember, season 4) -- Besides that, maybe we can help</em>
<h2>Catching NameError</h2>

<pre class="python">
try:
   import foo
except ImportError:
   pass

try:
   foo.Function()
except NameError:
   pass # some replacement
</pre>
<ul><li>Bad idea!</li>

</ul>
<hr />
<em>Piper (Morality Bites, season 4) -- That's OK, I forgot your name too.</em>
<h2>Catching NameError (cont'd)</h2>

<pre class="python">
try:
   import foo
except ImportError:
   foo = None

if foo is not None:
   foo.Function()
else:
   pass # some replacement
</pre>
<ul><li>If foo.Function() sometimes has a NameError, we won't mask it...</li>

<li>...or if we misspell 'foo'</li>

</ul>
<hr />
<em>Anne (Morality Bites, season 4) -- Oh, right, sorry.</em>
<h2>Importing Modules -- A Review</h2><ul>
<li>'import module'</li>

<li>'from module import name1, name2'</li>

<li>Only imports once (or does it?)</li>

</ul>
<hr />
<em>Phoebe (Animal Pragmatism, season 2) -- Rome was not built in a day,</em>
<h2>Importing __main__</h2><ul>
<li>__main__ is where the 'script' is executed</li>

<li>Avoid the temptation to import __main__</li>

<li>Put common function in a named module</li>

<li>Then your code will be more useful</li>

</ul>
<hr />
<em>Piper (Animal Pragmatism, season 2) -- And why mess with a good thing?</em>
<h2>Importing a File Twice</h2><ul>
<li>But it can't be, can it?</li>

<li>Importing a script into itself</li></ul>

<pre class="python">
# file: hello.py
import hello
class Foo: pass
</pre>
<ul><li>Two 'Foo's, same definition, different class!</li>

<li>If your sys.path includes packages...</li>

<li>...you can import a module once from a package and once plain</li>

</ul>
<hr />
<em>Phoebe (Which Prue Is It, Anyway?, season 1) -- Okay, which one of you is the real Prue?</em>
<h2>Importing *</h2><ul>
<li>Don't do it<ul><li>Don't do it</li>
</ul></li>

<li>Classic mistake:</li></ul>

<pre class="python">
from os import *

fp = open("file") # works
fp.readline() # fails with a weird error...?
</pre>
<ul><li>os.open returns a file descriptor (number)</li>

</ul>
<hr />
<em>Pink Prue (Which Prue Is It, Anyway?, season 1) -- So, um, what did I do now?</em>
<h2>Importing * Inside Functions</h2><ul>
<li>Just invalid Python...</li>

<li>...but happens to work in 1.5.2...</li>

<li>...and sometimes in 2.1...</li>

<li>...never in 2.2.</li>

<li>Just Say No</li>

</ul>
<hr />
<em>Pink Prue (Which Prue Is It, Anyway?, season 1) -- What ever it is, I have an alibi.</em>
<h2>Importing Names</h2><ul>
<li>from foo import name1, name2</li>

<li>Not a bad idea always</li>

<li>But be careful of repercussions:</li>

<li>modules sometimes change things inside</li>

<li>You won't see those changes</li>

<li>Opportunity for inconsistency!</li>

</ul>
<hr />
<em>Real Prue (Which Prue Is It, Anyway?, season 1) -- Because I still have to work here when all of this is over.</em>
<h2>Reloading</h2><ul>
<li>reload(module) -- reread module from file</li>

<li>Useful in long running processes?</li>

<li>Doesn't play nice with 'from import name'</li>

<li>Beware of exceptions: the new classes are different from old classes</li>

</ul>
<hr />
<em>Real Prue (Which Prue Is It, Anyway?, season 1) -- Don't worry I'm never casting that spell again.</em>
<h2>exec, execfile and eval</h2><ul>
<li>Execute arbitrary Python code</li>

<li>No-cost scripting language for applications</li>

<li>But easy to shoot one's self in the foot</li>

</ul>
<hr />
<em>Reporter (Morality Bites, season 2) -- More news on the execution of Phoebe Halliwell coming up.</em>
<h2>exec, execfile and eval -- Modify namespaces</h2><ul>
<li>They modify the namespace they're in<ul><li>...but not always.</li>
</ul></li>

<li>Depends on global vs. inside functions</li>

<li>Use with care -- or with explicit dictionaries</li>

</ul>
<hr />
<em>Nathaniel (Morality Bites, season 2) -- Executions are a bitch to plan.</em>
<h2>exec, execfile and eval -- Inside functions</h2><ul>
<li>Unadorned exec is invalid inside functions</li>

<li>execfile and eval play badly with local var. optimisation</li>

<li>Always use with explicit dictionary</li>

</ul>
<hr />
<em>Nathaniel (Morality Bites, season 2) -- Phoebe, what is this? An attempt to stay your execution?</em>
<h2>Conclusion: recommended usage</h2><ul>
<li>d={};exec "code" in d</li>

<li>d={};execfile("file", d)</li>

<li>d={};eval("expression", d)</li>

<li>Sometimes useful to pre-populate dictionary</li>

</ul>
<hr />
<em>Phoebe (Morality Bites, season 2) -- Just because you don't understand something, doesn't make it evil.</em>
<h2>exec, execfile and eval -- Restricted Execution (Don't)</h2><ul>
<li>rexec never was audited</li>

<li>History of holes</li>

<li>Dangerous to allow arbitrary code</li>

<li>DoS attacks not defended against at all</li>

<li>Recursion</li>

</ul>
<hr />
<em>Leo (Morality Bites, season 2) -- Nobody's gonna rescue you.</em>
<h2>Syntax</h2><ul>
<li>Python syntax regular and nice...</li>

<li>...but not perfect.</li>

<li>Some care needed.</li>

</ul>
<hr />
<em>Prue (Morality Bites, season 2) -- You know, we can still make the good things happen.</em>
<h2>Syntax -- Tabs and Spaces</h2><ul>
<li>Use Tabs</li>

<li>Or use spaces</li>

<li>But don't mix them...</li>

<li>...ever!</li>

<li>Invites bugs</li>

</ul>
<hr />
<em>Prue (The Painted World, season 2) -- We've seen so many bizarre things.</em>
<h2>Syntax -- Backslash Continuations</h2>

<pre class="python">
# Extra newline
r = 1 \

+2

# Missing backslash in long series
r = 1 \
+2 \
+3 \
+4 
+5 \
+6
</pre>
<ul><li>Both *silently* do the wrong things</li></ul>

<h2>Syntax -- Backslash Continuations (cont'd)</h2>

<ul><li>Better</li></ul>

<pre class="python">
# Extra newline
r = (1

+2)

# Long series
r = (1
+2
+3
+4
+5
+6)
</pre>

<hr />
<em>Prue (The Painted World, season 2) -- Uh, what just happened here?</em>
<h2>Hand Hacking Batteries</h2><ul>
<li>Don't write os.path functions yourself<ul><li>os.path.join especially</li>
</ul></li>

<li>min, max</li>

<li>urlparse</li>

<li>Skim through modules list. A lot.</li>

</ul>
<hr />
<em>Prue (Animal Pragmatism, season 2) -- Well, we didn't find anything in the Book Of Shadows.</em>
<h2>Further Reading</h2><ul>
<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>

<li><a href="http://www.amk.ca/python/writing/warts.html">http://www.amk.ca/python/writing/warts.html</a></li>

<li><a href="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</a></li>

</ul>
<hr />
<em>Phoebe (The Painted World, season 2) -- I think you'll find me pretty knowledgeable about all areas</em>
<h2>Questions?</h2>
<em>Piper (The Painted World, season 2) -- You're like ask rainman.com</em>

<h2>Bonus Slides</h2>
<em>Phoebe (The Painted World, season 2) -- Oh, and P.S. there will be no personal gain.</em>

<h2>Packages and __init__.py</h2><ul>
<li>Packages are determined by __init__.py files</li>

<li>Temptation to put code in __init__.py</li>

<li>But two namespaces mix: __init__'s and filesystem's</li>

<li>Put comments, docstring and __all__</li>

</ul>
<hr />
<em>Piper (Animal Pragmatism, season 2) -- It's a package. One I would like to share with you.</em>
<h2>Type Checking</h2><ul>
<li>Python's typing is highly dynamic</li>

<li>Capability-based, not class-based</li>

<li>Explicit type checks hurt code usefulness</li>

<li>(common use -- proxies, for testing)</li>

</ul>
<hr />
<em>Phoebe (Black as Cole, season 2) -- I never thought of myself as the marrying type</em>
<h2>Type Checking -- Example</h2><ul>
<li>Here's what not to do:</li></ul>

<pre class="python">
class Foo:
    def __init__(self, i):
        if type(i) is types.StringType:
            self.content = open(i).readlines()
        elif type(i) is types.ListType:
            self.content = i
</pre>
<ul><li>(inspired from a question on #python)</li>

<li>More badness than you can shake a stick at.</li>

</ul>
<hr />
<em>Phoebe (Muse to My Ears, season 4) -- You're an artistic, creative type.</em>
<h2>Type Checking -- Example -- Fixed</h2>
<pre class="python">

class Foo:
    pass

class FooFromFile(Foo):

    def __init__(self, filename):
         self.content = open(filename).readlines()

class FooFromList(Foo):

    def __init__(self, list):
         self.content = list
</pre>

<hr />
<em>Phoebe (Muse to My Ears, season 4) -- You see how well this worked out?</em>
<h2>Private __Attributes</h2><ul>
<li>Useful in deep hierarchies to keep attributes separate</li>

<li>Mangle only class name -- *not* module name</li>

<li>Makes it harder to test</li>

<li>Makes it harder to hand-hack for debugging</li>

</ul>
<hr />
<em>Tessa (Animal Pragmatism, season 2) -- Maybe it's our fault because we tried to make them into something they're not.</em>

<h2>Using Mutable Default Arguments</h2>

<pre class="python">
def foo(l=[]):
    l.append(5);return l
</pre>

<ul>
<li>Will modify the same list.</li>
<li>If you want that -- use object, class, not that hack.</li>
</ul>

<pre class="python">
def foo(l=None):
    if l is None: l=[]
    l.append(5);return l
</pre>
<hr />
<em>Snake guy (Animal Pragmatism, season 2) --
You two are acting like nothing's changed.</em>

</body></html>