Why is this legal?

  • Thread starter Michael George Lerner
  • Start date
M

Michael George Lerner

I tracked down a bug today that boiled down the "undecorate" part of
this "decorate-sort-undecorate":

cluster = [(c.resi,c) for c in cluster] # decorate
cluster.sort() # sort
cluster = [c for (c.resi,c) in cluster] # undecorate

That last line actually assigns c.resi for each c in cluster.

Here's a simple example of the same thing:

[mlerner@localhost mlerner]$ python
Python 2.3b2 (#1, Jul 3 2003, 14:20:37)
[GCC 3.2.2 (Mandrake Linux 9.1 3.2.2-3mdk)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
class Foo: pass ....
f1 = Foo(); f2 = Foo()
f1.x = 'go'; f2.x = 'od'
f1.x+f2.x 'good'
things = [f for (f,f.x) in [(f1,'bo'),(f2,'gus')]]
f1.x+f2.x 'bogus'


Is there any reason you'd ever want to do this?

I use pychecker, but I've never actually looked at how it works.
Would it be hard to make pychecker detect something like this?

-michael
 
J

Jeff Shannon

Michael said:
f1 = Foo(); f2 = Foo()
f1.x = 'go'; f2.x = 'od'
f1.x+f2.x
'good'

things = [f for (f,f.x) in [(f1,'bo'),(f2,'gus')]]
f1.x+f2.x
'bogus'



Is there any reason you'd ever want to do this?

I don't know if there's a *reason* why you'd want to do this.

But note that if you rewrote the list-comp as a for loop, you'd have the
same effect and probably not be surprised by it. It's simply a matter
that for loops (and list comprehensions) do not introduce a new scoping
level in Python.

Jeff Shannon
Technician/Programmer
Credit International
 
R

richard

Michael said:
cluster = [c for (c.resi,c) in cluster] # undecorate

That last line actually assigns c.resi for each c in cluster.

Is there any reason you'd ever want to do this?

Yes, I've done it many times.


Richard
 
G

Gary Herron

I tracked down a bug today that boiled down the "undecorate" part of
this "decorate-sort-undecorate":

cluster = [(c.resi,c) for c in cluster] # decorate
cluster.sort() # sort
cluster = [c for (c.resi,c) in cluster] # undecorate

That last line actually assigns c.resi for each c in cluster.

So if you don't want to assign to c.resi don't use it as a loop
variable:
cluster = [c for (ignored,c) in cluster] # undecorate
or
cluster = [item[1] for item in cluster] # undecorate
Is there any reason you'd ever want to do this?

There is a big reason to want it to stay this way. The rule that
"each pass through the loop rebinds the loop variable (or tuple of
loop variables)" is simple, and clear. For that reason alone, we
don't want to ever change it.

Gary Herron
 
M

Michael George Lerner

Gary Herron said:
I tracked down a bug today that boiled down the "undecorate" part of
this "decorate-sort-undecorate":

cluster = [(c.resi,c) for c in cluster] # decorate
cluster.sort() # sort
cluster = [c for (c.resi,c) in cluster] # undecorate

That last line actually assigns c.resi for each c in cluster.
So if you don't want to assign to c.resi don't use it as a loop
variable:
cluster = [c for (ignored,c) in cluster] # undecorate
or
cluster = [item[1] for item in cluster] # undecorate

Yup. I rewrote it as
cluster = [c for (resi,c) in cluster] # undecorate
once I found the bug.

I think I was just annoyed that it was so easy to write the
undecorate line by copying the decorate line and moving terms
around .. easy, but broken.

You and Jeff Shannon have convinced me that I just need to make
sure that I don't forget that a list comprehension is really
just a cute for loop.

It still seems a little jarring, though.

Thanks,

-michael
 
A

Alex Martelli

Michael George Lerner said:
Heck, maybe I'll even download Python 2.4 so I can say
cluster.sort(key=lambda c: c.resi)

Or better,
cluster.sort(key=operator.attrgetter('resi'))

This way it will really fly!


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,206
Messages
2,571,069
Members
47,675
Latest member
RollandKna

Latest Threads

Top