Sunday, March 29, 2009

Python Tuple and List Comprehension

As far as I know python does not support tuple comprehension.

For any readers not familiar with list comprehension, run this:


c = [i for i in range(10)]


It's a short hand way to create lists, if you currently would have done this:

c = []
for i in range(10):
c.append(i)
#end for


STOP!

You are wasting valuable time and brain power, learn list comprehensions, they will be foreign at first (when you're doing complicated ones), but after struggling through it a few times they will become second nature.

Now as far as tuple comprehension, here is my gripe: Python can't do it (edit: read the end of this post to see otherwise)!

You have to do this:

c = tuple([i for i in range(10)])


But here is my real gripe... people that think they know all the ways people are using a given toolset, read this posting from a mailing list about tuple comprehensions:

From http://mail.python.org/pipermail/python-list/2002-April/139269.html

[quote]
.... Even if we *could* make the parser smart
enough to recognize a tuple-comp, it would be confusing to read,
at least IMO.

I also agree with Dave Brueck, that the cases in which tuples
hold uniform values (so that tuple comprehensions might make
sense) are relatively rare, compared to cases in which tuples
hold heterogeneous values. (This is exactly the opposite case of
lists, which may be heterogeneous but are usually homogenous.)
So ISTM that tuple comprehensions would be of limited utility.
[/quote]

The difference between tuples and lists is that you can't change tuples, once they're made, thats it, can't add, can't remove, can't even set an existing element equal to something else.

So that's the real reason why tuple comprehension doesn't make sense, when you expand it (in your head) it looks like this:


c = ()
for i in range(i):
c.append(i)
#end for


And you can't append to a tuple, but anyway, the parser COULD be smart enough to expand it like this:

c = (0,1,2,3,4,5,6,7,8,9)

However this could only be done by the parser on very simple tuple comprehensions.

I'm not saying if it SHOULD or SHOULDN'T, just that it COULD.

Here is a slightly more complicated list comprehension, that I wish I could have done tuple comprehension on:

Background: on a mysqldb cursor object...
cursor.execute('select id from table')
all = cursor.fetchall()
print all
((1L,), (3L,), (4L,))

Ok, so we have a tuple of one length tuples contain the ids... I want to change this to just a tuple of ids, ie: (1,3,4)

so I do list comprehension and then create a tuple from the list:
c = tuple([id[0] for id in all])

There you go, a very real world problem where tuple comprehension would have been very nice.

Personally, I think if tuple comprehension was ever introduced to the language that it should actually use this syntax: tuple(i for i in range(10)), or tuple([i for i in range(10)]) (although this might be slightly misleading, it shouldn't break existing code and offer a performance boost). You couldn't use (i for i in range(10)) because its already used to create a generator.

-----

This is hilarious, after I wrote that, I thought, maybe the people who add features to python already have done this? Since that mail list post I referenced is from 2002 or something... guess what, looks like tuple(i for i in range(10)) works, so there you have it, tuple comprehension IS supported!

I'm going to leave this post as is, as a warning to all you know-it-alls who think, retarded things tuple generation would have "limited utility"

1 comment:

furrykef said...

"tuple(i for i in range(10))" works because the "i for i in range(10)" produces a generator, which in turn is passed to tuple(). Try this at the interactive prompt:

>>> x = (i for i in range(10))
>>> x
<generator object at 0x00BC4878>