The following are a quick (random, off the top of various heads) list of
things that I think are
anti-pitfalls in Python. That is, because the language has these
features, it is harder to make programming mistakes.
Thanks to Dougal, Anthony and Toby for running their eyes over this
list, and for their suggestions.
1. Everything's a reference to an object (no magic line-noise)
Python doesn't have a separate scalar / reference syntax! Celebrate!
Dereferencing is one of the hardest concepts for a new programmer to learn,
and I know from personal experience that some people gave up on the whole
programming caper just because they didn't understand pointer
arithmetic and dereferencing in C.
Aside: perhaps it might be because it's such a fundamental pitfall in
other languages that people coming from them have such trouble
coping with python's "names for objects" approach. How many times have we
seen new Python programmers despairingly ask "how do I pass by reference"?
Pitfall avoided:
Many and various errors due to not getting the magic line-noise quite
right or not fully understanding the concept of dereferencing.
2. Real polymorphism
(or rather, not that jumping-through-hoops, interface-tied,
type-casting-up-the-wazoo anticipate-all-use-cases polymorphism that some languages force on
users)
Everything's an object and there's no built-in type checking on arguments.
Interfaces generally evolve through consensus - if a function is written
that accepts a file object argument to read data from, then any
object that implements a read() method will do as a substitute argument - a
StringIO instance, the result of a urllib.urlopen() call, a socket, etc.
Combine with built-in variable argument lists and keyword argument lists (with
default values) for a really satisfying taste!
Pitfall avoided:
Inflexibility due to not anticipating some new use of your code.
3. Sequence unpacking
I use it so much. Mostly just automatically too when returning
multiple values from a method/function. And "a,b = b,a" does the right
thing.
Pitfall avoided:
Messy code.
4. The call operator
Bound methods, functions, classes... all use exactly
the same interface and all are first-class objects.
Pitfalls avoided:
Having to deal with (and remember) the different ways of calling different
callable things. Also, like #2 you don't have to worry about what kind
of callable you might get if you accept one as a function argument.
5. Automatic memory management
W00t!
Also under this heading could be the complete inability of user
input to mangle code and take over your system (caveat: no use of
exec/eval).
Pitfalls avoided:
Memory usage going out of control. Your system being compromised because
you didn't bounds-check some string from the Real World.
6. The print statement
A lot of other languages have a print statement or function but Python's is
particularly good at just dumping a bunch of information in human-readable
form. It just works. This is mostly because many/most builtin
objects have useful repr methods.
BTW, I think it's a good thing that it adds spaces, even with a dangling
comma. If I want fine control over output, I'll use sys.stdout.write().
Pitfall avoided:
Inability to just have a gander at what's going on.
7. Indentation for structure
Not only does this save typing, but it also means that code is far more
readable than in some other languages.
Pitfalls avoided:
Unreadable code. Strange errors due to not using block delimeters when you
should have used them.
8. Ubiquitous, unencumbering exception system
It's available and used everywhere, and you don't have to trap exceptions
if you don't want to. Trapping exceptions can be as fine-grained as you
like, and you can send an arbitrary object of information along with the
exception. Now that's nice.
9. Introspection
From Dougal: you can poke into any object. You can test whether objects
have attributes, or whether they're callable, or...
Pitfall avoided:
Like #6, you can get in there to understand what's
really going on in your own code.
It can be argued that a lot of problems are averted just by having the
solid built-in string, tuple, list and dictionary types. The potential
problems in other languages being errors in
implementing those types or using half-assed attempts at implementing them.
Pitfall avoided:
Half-assed basic type (re-)implementations.
11. No namespace pollution (unless you really want to)
Another from Dougal: Python doesn't automatically pollute namespaces unless
you specifically force it to with statements like "from foo import *".
Pitfall avoided:
Namespace pollution, and the strange side-effects that occur.
12. The python shell (interactive interpreter)
From Toby: "if for no other reason than that i don't need a calculator
any more ;)". I definitely echo that sentiment, and more...
The interactive interpreter prompt lets new and experienced Python users
alike muck around with code to see what it does. I couldn't imagine
developing regular expressions without the interactive shell :)
Pitfall avoided:
This is more a tool for avoiding a bunch of errors you might have run into
without the ability to test ideas and code fragments out.
13. PDB
From Anthony: PDB, the built-in debugger. I'm not sure this consitutes
an anti-pitfall, but it's definitely on his list. The magic string you're
looking for is "import pdb ; pdb.set_trace()"
When the code hits that you'll be dropped into the pdb shell. Nice.
Pitfall avoided:
When things do go wrong, you've got the direct ability to get
elbow-deep in the live program to see why it went wrong. And to change that
live program then and there if necessary.
14. Treat programmers with respect
Python treats programmers as intelligent people. It doesn't specifically
put barriers
in their way which can cause confusion (eg. public/private/protected
attribute distinctions that are circumventable in some other language
implementations anyway, leading to horrible, horrible code).
Pitfall avoided:
Treating programmers like babies, asking them to be overly explicit in
every little thing they do, and locking them out from things that they
might hurt themselves on.