Tue, 02 Sep 2003
Python anti-pitfalls

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.

10. Feature-full, rock-solid, simple built-in types
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.

path: /python | permanent link |