# 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.python-list 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
|

```