2.20.2008

python: reference anonymous list created by list comprehension

When using a list comprehension, the list created under the hood can be referred to with locals()['_[1]']. In the case of nested elements, the elements are named _[2], _[3], etc, as you delve deeper into the nested items. The 'anonymous' list exists only while the list comprehension executes,ie. only during the work between '[' and ']'. It's sometimes handy to be able to refer to this list for in-line processing during the list comprehension. Here's an easy example. Let's say I wanted to join three lists together, removing any duplicate elements:

>>> L1 = [ 1,2,3 ]
>>> L2 = [ 2,3,4 ]
>>> L3 = [ 2,4,5 ]
>>> [ x for x in L1 + L2 + L3 if x not in locals()['_[1]'] ]
[1, 2, 3, 4, 5]

Now, the 'gotcha' is that locals()['_[n]'] is not just incremented for each nested list comprehension, it's incremented whenever a list comprehension is used in the local scope. So, if you've executed four list comprehensions previously in the run of the local scope, your next one is referenced as locals()['_[5]']. This is most evident within a loop:
>>> for x in [1,2,3]:
... [ x for x in l1 + l2 + l3 if x not in locals()['_[1]'] ] #this will work
... [ x for x in l1 + l2 + l3 if x not in locals()['_[1]'] ] #this key no longer exists
...
[1, 2, 3, 4, 5]
Traceback (most recent call last):
File "", line 3, in
KeyError: '_[1]'

>>> for x in [1,2]:
... [ x for x in l1 + l2 + l3 if x not in locals()['_[1]'] ]
... [ x for x in l1 + l2 + l3 if x not in locals()['_[2]'] ] #here's the increment
...
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]




2 comments:

Chimera said...

Did you give up on this blog or just start a new one?

stewpid said...

Hehe, I guess I've just had nothing interesting to say for a year. =]