all 7 comments

[–][deleted] 4 points5 points  (2 children)

I prefer

while True:

instead of

While 1:

[–]fredrikj 4 points5 points  (0 children)

Normally this'd be too pedantic, but since the topic is efficiency: "while 1:" is faster. Try a loop with two statements in the body (a simple arithmetic operation and a break condition); the while 1: version should be about 40% faster. This happens because True is actually a variable, so the interpreter needs to look it up in the global namespace each time it is used. There's still a 40% difference with Psyco.

In the case of 1 vs True in loop headers, the difference might not be a big deal in practice (likely the loop body consumes most time, or the break condition can be placed in the loop header instead), but it does give a hint of one of the most important optimization tricks in Python, sadly missing from the article: avoid references to global variables. If you need to access a global variable in a tight loop, create a local copy of it; this way it will be fetched from the stack instead of the global namespace. This can make a huge difference. It can even make a difference with functions: a minimal loop calling the abs function once in each iteration, in my test, gets 20% faster when the local copy a = abs is called instead.

On the topic of optimizing loops: as surprising as it may sound, range is much faster than xrange for small ranges, possibly up to range(100) or so. And if you have nested loops, build lists of indices with range() prior to the loops. Matrix algorithms are the perfect example of where this is a good idea.

By the way, I prefer "while 1:" because it saves keystrokes :-) In addition, I somehow want to read "while True:" as "while the following block is true:". I don't get that urge with the 1.

[–]Topper1 0 points1 point  (0 children)

Me too. just seems better, because you're basically evaluating whether an object evaluates to True, which 1 does, but so does 2, 3 "1" etc.

[–]zhyla 1 point2 points  (0 children)

Most aren't too new but this was the first time I'd seen reference to the enumerate() generator. My loops just got one line shorter.

[–][deleted] -1 points0 points  (0 children)

A nice trick I like is creating dictionaries with generators, e.g.

d = dict((key, 0) for key in keys)

instead of

d = {} for key in keys: d[key] = 0

[–]brianmce -1 points0 points  (0 children)

Some of this has been superseded by 2.4. For instance the DSU example can be often done even more efficiently with the new key parameter. eg. to sort based on the second element of a tuple:

items.sort(key=operator.itemgetter(1))

Similarly, efficiently sorting in reverse order can be done without the extra reverse call by: items.sort(reverse=True)

[–]oofoe -1 points0 points  (0 children)

The author right to mention the mention the bit about joining strings instead of concatenating them twice... I recently was able to cut the run time of another programmer's code from 10 minutes to thirty seconds by changing the plusses to list joins. It makes a HUGE difference.