Re: Stupid Python Tricks #2

Tim Peters (tim@ksr.com)
Thu, 16 Sep 93 22:08:18 -0400

"Python tricks" is a tough one, cuz the language is so clean. E.g., C
makes an art of confusing pointers with arrays and strings, which leads
to lotsa neat pointer tricks; APL mistakes everything for an array,
leading to neat one-liners; and Perl confuses everything period, making
each line a joyous adventure <wink>.

I've seen Python criticized as "ugly" precisely because it _doesn't_ have
a trick-based view of the world. In many ways, it's a dull language,
borrowing solid old concepts from many other languages & styles: boring
syntax, unsurprising semantics, few automatic coercions, etc etc. But
that's one of the things I like about it.

The trickiest areas in my experience have to do with namespace
management, both the cool way classes introduce dynamic new namespaces,
and the way assignment in general merely binds a name to an object. You
can do some very powerful things after grasping these, but they're
already illustrated well in the distributed Python samples.

The most practical-- but mundane --"trick" I've stumbled into is a speed
trick, when using a dict to accumulate info, and accesses to existing
keys outnumber new keys. E.g.,

try: dict[key] = dict[key] + 1
except KeyError: dict[key] = 0

can run a good deal faster than

if dict.has_key(key):
dict[key] = dict[key] + 1
else:
dict[key] = 0

I imagine that's because the latter looks up the key 3 times, instead of
twice in the former, in the usual (the key is usually present, by
supposition) case.

But then putting a little smarts into the translator would allow either
form to map into runtime code that did only 1 key lookup. What I'd
_really_ like to write is (a la C, Icon, Perl, etc)

try: dict[key] += 1 # hypothetical augmented assignment operator '+='
except KeyError: dict[key] = 0

I.e., to be able to write it in a way that a mindless translator would
usually map to a single key lookup.

> ...
> challenge to see how many different ways we can find to write a
> simple python program - sort of like the 4000 different ways to
> print "Just another PERL hacker" that you always see in the sigs
> on Comp.lang.perl.

Hey, I'm game <grin>! Here's another way to write reverse:

def rev( x ):
l2 = len(x)/2
if l2:
return rev(x[l2:]) + rev(x[:l2])
else:
return x

It works for strings/tuples/lists/user_sequences, and has the practical
advantage that the call stack doesn't grow deeper than log2(len(x)).

>>> rev((rev('rekcah'),rev('nohtyP'),rev('rehtona'),rev('tsuJ')))
('Just', 'another', 'Python', 'hacker')
>>>

even-obfuscated-python's-darned-easy-to-read-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp