The Secret Name of List Comprehensions
The Secret Name of List Comprehensions (Python recipe) by Chris Perkins
5
|
Sometimes you want to have a list comprehension refer to itself, but you can't because it isn't bound to a name until after it is fully constructed. However, the interpreter creates a secret name that only exists while the list is being built. That name is (usually) "_[1]", and it refers to the bound method "append" of the list. This is our back door to get at the list object itself.
While list comprehensions look a little like magic, the bytecode generated for them is quite mundane - create an empty list, give its append method a temporary name in the locals dictionary, append items one at a time, and then delete the name. This all happens, conceptually, between the [ and the ] that denote the list comprehension. The temporary name assigned is "_[1]" (or "_[2]" for a nested list comprehension). Since this is not a syntactically valid Python identifier, we cannot refer to it directly - we need to access it as locals()['_[1]']. Then we just use the bound method's __self__ attribute to get at the list object itself. This lets us do all sorts of neat party tricks, like performing "if" tests that involve looking at the items that have already been added to the list - or even modifying or deleting them. This is just what the doctor ordered for finding primes in a one-liner - for each odd number we need to test whether it is divisible by any prime number less than or equal to the square root of the number being tested. Since we already have all the smaller primes stored, and, with our new parlour trick, have access to them, this test is a breeze and requires no auxiliary storage. Note that while the prime number functions above are pretty fast for one-liners (plt(100000) takes 7 seconds on my machine, timed with the ultra-accurate "counting-in-my-head" method), they are nowhere near as fast as the Sieve of Eratosthenes method (recipe 117119). However, they are much, much sexier. ;) And now for the big "but"... It should come as no surprise to anyone that this is a totally undocumented, seat-of-your-pants exploitation of an implementation detail of the Python interpreter. There is absolutely no guarantee that this will continue to work in any future Python release. In fact I only know for sure that it works in Python 2.2.2 and 2.3b1. Beyond that you're on your own. Finally, as an aside, let me just say: itertools rules!
Tags: shortcuts
|