Why is this legal?

Discussion in 'Python' started by Michael George Lerner, Sep 8, 2004.

  1. 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
    Michael George Lerner, Sep 8, 2004
    #1
    1. Advertising

  2. Michael George Lerner

    Jeff Shannon Guest

    Michael George Lerner wrote:

    >
    >>>>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
    Jeff Shannon, Sep 8, 2004
    #2
    1. Advertising

  3. Michael George Lerner

    richard Guest

    Michael George Lerner wrote:
    > 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
    richard, Sep 9, 2004
    #3
  4. Michael George Lerner

    Gary Herron Guest

    On Wednesday 08 September 2004 02:05 pm, Michael George Lerner wrote:
    > 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
    Gary Herron, Sep 9, 2004
    #4
  5. Gary Herron <> wrote:
    > On Wednesday 08 September 2004 02:05 pm, Michael George Lerner wrote:
    >> 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

    >> 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
    Michael George Lerner, Sep 9, 2004
    #5
  6. Michael George Lerner <> wrote:
    ...
    > 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
    Alex Martelli, Sep 9, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Valentin Tihomirov

    Is this legal?

    Valentin Tihomirov, Oct 21, 2003, in forum: VHDL
    Replies:
    20
    Views:
    1,241
    Jan Decaluwe
    Oct 29, 2003
  2. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    874
    Mark Rae
    Dec 21, 2006
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,803
    Smokey Grindel
    Dec 2, 2006
  4. Universe
    Replies:
    6
    Views:
    307
    Universe
    Mar 26, 2011
  5. Gavin Kistner
    Replies:
    3
    Views:
    125
    Gavin Kistner
    Jan 29, 2004
Loading...

Share This Page