an ingrate newbie complains
Elaine Jackson
elainejackson7355 at home.com
Thu Feb 5 01:22:03 CET 2004
Thanks to everyone who responded. Digging into this matter of list
comprehensions a bit more, I turned up some interesting facts. Consider the
following example:
>>> f = lambda x,y: x*y+2*pow(y,2)
>>> g = lambda x: 3*pow(x,2)
>>> list = [1,2,3,4,5]
The kind of expression I have in mind would be equivalent to...
>>> [f(x,y) for (x,y) in [(x,g(x)) for x in list] if y>19]
[1539, 4800, 11625]
...which is equivalent to...
>>> [f(x,y) for x in list for y in [g(x)] if y>19]
[1539, 4800, 11625]
...but it's not equivalent to...
>>> [f(x,y) for y in [g(x)] if y>19 for x in list]
[11325, 11400, 11475, 11550, 11625]
...or to...
>>> [f(x,y) for y in [g(x)] for x in list if y>19]
[11325, 11400, 11475, 11550, 11625]
I imagine a good explanation of this discrepancy can only be gotten by dipping
into the documentation and finding out what an "iterator" is, and that's
unfortunate (imho), because it means that list comprehensions fail to
"intuitively suggest the proper meaning to a human reader who has not yet been
introduced to the construct" (quote taken from the FAQ).
del list
## Peace
"Skip Montanaro" <skip at pobox.com> wrote in message
news:mailman.1212.1075922934.12720.pythonlist at python.org...

 Elaine> 1) I find the following behavior puzzling and disappointing:

 >>> X=[(1,1),(2,4),(3,9),(4,16),(5,25)]
 >>> Y=dict(X)
 >>> Z=list(Y)
 >>> Z==X
 False
 >>> Z==Y.keys()
 True

 That list(Y) returns the keys of X is perhaps unfortunate, but the same
 behavior allows you to write:

 for key in Y:
 print (key, y[key])

 which can be an efficiency gain if Y is large (not having to build a list of
 all the keys ahead of time). You'll find this to be true though:

 W = Y.items()
 W.sort()
 W == X

 Elaine> 2) How come you can't write...

 Elaine> if y = f(x) > 3:
 Elaine> <do a bunch of things with x and y>

 There is a common class of errors in C code:

 if (c = 0) {
 ...
 }

 Is that supposed to be an assignment or a test? Python avoids that problem
 by not allowing assignments within expressions.

 Elaine> That kind of syntax would be especially welcome in list
 Elaine> comprehensions:

 Elaine> [f(x,y) for x in list if y=g(x)<=0]

 I think you can recast that as:

 [f(x,y) for (x,y) in zip(list, [g(z) for z in list]) if y <= 0]

 but do you really want to? (This won't work if list is an iterator.)

 Elaine> If g(x) is a fairly complicated expression, and y occurs several
 Elaine> times in f(x,y), considerable clarity could be gained.

 If g(x) is a fairly complicated expression and y occurs several times in
 f(x,y), perhaps you should be using a for loop instead of a list
 comprehension:

 result = []
 for x in list:
 y = g(x)
 if y <= 0:
 result.append(f(x,y))
 return result

 (FYI, you shouldn't use "list" as a variable name. You're shadowing a
 builtin, a practice that can lead to confusing error messages, if nothing
 else.)

 Skip

More information about the Pythonlist
mailing list