if you are generating bits of a string sequentially instead of:
s = "" for x in list: s += some_function(x)
slist = [some_function(elt) for elt in somelist] s = "".join(slist)
out = "<html>" + head + prologue + query + tail + "</html>"
out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)
Suppose you can’t use map or a list comprehension? You may be stuck with the for loop. The for loop example has another inefficiency. Both newlist.append and word.upper are function references that are reevaluated each time through the loop. The original loop can be replaced with:
upper = str.upper newlist =  append = newlist.append for word in oldlist: append(upper(word))
This technique should be used with caution. It gets more difficult to maintain if the loop is large. Unless you are intimately familiar with that piece of code you will find yourself scanning up to check the definitions of append and upper.
The Python interpreter performs some periodic checks. In particular, it decides whether or not to let another thread run and whether or not to run a pending call (typically a call established by a signal handler). Most of the time there’s nothing to do, so performing these checks each pass around the interpreter loop can slow things down. There is a function in the sys module, setcheckinterval, which you can call to tell the interpreter how often to perform these periodic checks. Prior to the release of Python 2.3 it defaulted to 10. In 2.3 this was raised to 100. If you aren’t running with threads and you don’t expect to be catching many signals, setting this to a larger value can improve the interpreter’s performance, sometimes substantially.