Interesting philosophical points.<p>To me personally, testing for 'truthy' and 'falsy' values, or relying on exceptions rather than checking values in advance, feels like sloppy and imprecise programming.<p>A string being empty or not, or an array having items or not, or a boolean being true or false, are all qualitatively totally different things to me -- and just because Python <i>can</i> treat them the same, doesn't mean a programmer <i>should</i> take advantage of that fact. Sometimes it's possible to <i>over</i>-simplify things in a way that obfuscates instead of clarifying.<p>When I read:<p><pre><code> if name and pets and owners
</code></pre>
I have no intuitive idea of what that means, of what's going on in the program. When I read<p><pre><code> if name != '' and len(pets) > 0 and owners != {}
</code></pre>
I understand it exactly.<p>But by this point, I've come to understand that, for a lot of people, it seems to be the opposite. It seems to be more of a philosophical difference, not right/wrong.
I disagree with promoting try / catch. Exceptions like ValueError can really happen almost anywhere, so it is usually better to sanitize your inputs.<p>E.g. something like:<p><pre><code> try:
something = myfunc(d['x'])
except ValueError:
something = None
</code></pre>
The programmer's intent is probably to only catch errors in the key lookup d['x'], but if there is some bug in the implementation of myfunc() or any of the functions called by myfunc() which causes a ValueError to unintentionally be raised, it will be caught by the except.<p>For dictionary lookups specifically, get() is usually preferable:<p><pre><code> something = d.get('x')
if something is not None:
something = myfunc(something)
</code></pre>
Or if dictionary may potentially contain None values:<p><pre><code> if 'x' in d:
something = myfunc(d['x'])</code></pre>
For point 10:<p>'_' is often aliased as gettext to ease translation of string:<p><pre><code> from django.utils.translation import ugettext as _
translated_str = _('Something to translate')
</code></pre>
so using it will overwrite the alias. Instead, you can use '__' (double underscore) as ncoghlan suggests below his answer [1].
or you can use the 'unused_' prefix as Google Python Style Guide suggests [2]
or you can change your code, so you don't need to use '_' as Alex Martelli suggests in his answer [3].<p>[1]: <a href="http://stackoverflow.com/a/5893946/720077" rel="nofollow">http://stackoverflow.com/a/5893946/720077</a><p>[2]: <a href="http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Lint#Lint" rel="nofollow">http://google-styleguide.googlecode.com/svn/trunk/pyguide.ht...</a><p>[3]: <a href="http://stackoverflow.com/a/1739541/720077" rel="nofollow">http://stackoverflow.com/a/1739541/720077</a>
The very first one, "Make a script both importable and executable," needs some caveats. It's useful sometimes, but people often use it in places where it is not a great idea. Here's why:<p>1) If you are in the mindset of "I want a single file which is both a library and a program," how will you name it? Files to import must end with ".py" and follow C-style name rules, so cannot start with a number cannot contain hyphens. This leads many people to break conventions when naming their programs, because on Unix, hyphens are conventional in program names but underscores are not (count the examples of each in /usr/bin on any system). And naming your program something like "2to3" is impractical if you want it to be importable also.<p>2) It is unclear where to install files which are both programs and libraries. Programs usually go in some sort of "bin" directory (again, on Unix systems), but libraries do not. Where do you put a file which is both?<p>3) Sometimes the __name__ == '__main__' trick is used to include unit tests within a module. That's not bad, but consider using Python's excellent doctest feature instead, which often serves the same need but in a richer way.
As an implementor of Hy (a homoiconic lisp frontend to Python) I've found certain Python idioms to be rather infuriating of late.<p>In particular:<p><pre><code> >>> 0 == False
True
</code></pre>
Which makes the idiom of testing truthiness quite annoying in parsing code such as:<p><pre><code> def is_digit_char(s):
""" Return a parsed integer from 's'."""
try:
return int(s)
except (ValueError, TypeError):
return None
</code></pre>
Which is harmless enough except that as a predicate it sucks because parsing "0" will return False in a context where I'd rather know whether I parsed an integer or not... which leads to non-idiomatic code.<p>This is mainly because True/False are essentially aliases for 1/0 and as such won't identify so:<p><pre><code> >>> 0 is False
False
>>> 0 is 0
True
</code></pre>
So it's important to remember another Tim Peters-ism: <i>Although practicality beats purity.</i> As read in the Zen of Python it seems he's referring to special cases which this might be.<p>As a shameless aside, you should see what we're working on in Hy. There will likely come a point where we'll be able to do kibit-style suggestions of idiomatic transformations to your Python code.<p><i>Update</i>: I ran into this while trying to write token parsers for a parser-combinator lib in Hy.
Although many of them boil down to preferences and philosophical points of view, I find these kinds of idioms useful. Whenever I write code in a new language, I want to "write as a native" so that I can maximize the effect that the language has on how I think about programming.<p>For Python in particular, Jeff Knupp's "Writing Idiomatic Python"[1] (not free, but not expensive, either) goes into detail on a lot of the concepts in the OP's slides. (I'm not affiliated with Jeff in any way, just a satisfied customer.)<p>[1] <a href="http://www.jeffknupp.com/writing-idiomatic-python-ebook" rel="nofollow">http://www.jeffknupp.com/writing-idiomatic-python-ebook</a>
Alex Martelli gave a nice talk called "Permission or Forgiveness" about the exception handling style recommended by OP: <a href="http://pyvideo.org/video/1338/permission-or-forgiveness-0" rel="nofollow">http://pyvideo.org/video/1338/permission-or-forgiveness-0</a>. He has some nice insights into this issue.<p>That being said, I think there are some situations where you want to check for problems up front (possibly in addition to exception handling). In particular, if you are parsing some data from outside the program, you may want to provide some context about what was wrong. KeyError is not very helpful to your users.
As a huge Python fan, I'm ashamed to admit but I don't get the<p><pre><code> while True:
break
</code></pre>
What's the problem? I supose the use case is<p><pre><code> while True:
# do stuff
if some_condition:
break
</code></pre>
What is the alternative? 'while some_condition'? That means we must have the 'some_condition' variable outside of the loop. And if we have multiple exit points it may become a mess.
I would add generator expressions:<p><pre><code> (f(x) for x in list_of_inputs)
</code></pre>
Just like a list comprehension, but with (...) rather than [...] and with lazy evaluation.<p>These are useful when you don't need to evaluate all of the inputs at once but still want to iterate over them at some point later on.
Thanks for this write up. I didn't know about enumerate. I never thought of swapping variables as in example 4 either.<p>I noticed one small mistake in section 9:<p><pre><code> d[keys] = values[i] </code></pre>
Should be:<p><pre><code> d[key] = values[i]</code></pre>
This is a great, if somewhat basic list. My $0.02: Python is a tool for thinking clearly. That you can run your "thoughts" as written is a very nice bonus, of course.<p>There are some really interesting things that Python allows:<p><pre><code> >>> d = {}
>>> d[23], d[14], d['hmm'] = 'abc'
>>> d
{'hmm': 'c', 14: 'b', 23: 'a'}</code></pre>
On page 20, didn't he/she mean "print(count, name)" in the BAD example?<p>On page 18, the Java comment: it depends. E.g. see [1]<p>[1] <a href="http://stackoverflow.com/questions/299068/how-slow-are-java-exceptions" rel="nofollow">http://stackoverflow.com/questions/299068/how-slow-are-java-...</a>
Another one that I find useful -- using `map` instead of list comprehensions when you want to apply a function to every element. So instead of:<p><pre><code> [str(x) for x in array]
</code></pre>
Do this:<p><pre><code> map(str, array)</code></pre>
>pets = ['Dog', 'Cat', 'Hamster']<p>>for pet in pets:<p>> print('A', pet, 'can be very cute!')<p>This may be nit picking but I prefer output like this:<p>print 'A %s can be very cute!' %(pet)
I don't understand the truth table on slide 9 for
" - vs None " and
"__nonzero__ (2.x) " __bool__ (3.x) vs __nonzero__ (2.x) " __bool__ (3.x) "
i agree with all but #2. this seems to embrace conciseness as simplicity or understandability. it forgets the more cardinal value that explicit is better than implicit.