Python is type-safe but dynamically typed -- no type declarations are needed. This gives flexibility and good support for rapid development, but it's also easy to write code that is difficult to understand and maintain. Here is a general rule of thumb: it should be possible to write the type signature of any Python variable or method, in a way that lets you statically check that there aren't any type violations. (Python doesn't require or even support such declarations, of course; this is a rule.) There are times you will want to violate this guideline, but make sure you have a good reason to do so.
For non-computer-science types, here are some practical implications of this heuristic:
True or False) when you need a
boolean value, not 0, 1, the empty string, or the other things that Python
allows for booleans.
type(x) or is,
there is very likely a better way to write it (using objects and
inheritance).
The ubiquitous ``resources'' variable is a violation of this rule, of course (which is why there is something a bit off about it); but for now, we just let this be an exception.
There are also a few typing style recommendations.
Tuples should in general just be used locally, if you are counting on elements being at specific positions -- if you need to pass around a tuple of this kind, define a small class instead. For example, this is a reasonable use of a tuple (for formatted text):
'Unexpected value -- squid was %s but %s was expected' % (a,b)
Here the tuple is used quite locally, and is clear.
However, if you find yourself passing around a tuple and then writing
things like squid[4][2][8], see if there is a better way to do it.
Similarly, lists used to package up a fixed number of elements, with the
positions being significant, are also suspect. (An exception is picking
apart the results from SQL queries -- here you're stuck with picking it
apart.)