python2.4 generator expression > python2.3 list expression

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • snacktime

    #1

    python2.4 generator expression > python2.3 list expression

    I need to convert a generator expression to a list expression so it
    will work under python 2.3.

    I rewrote this:

    for c in range(128):
    even_odd = (sum(bool(c & 1<<b) for b in range(8))) & 1

    As this:

    for c in range(128):
    bo = [bool(c & 1<<b) for b in range(8)]
    even_odd = sum(bo) & 1


    Seems to work, is there a better way to do this?
  • Steven Bethard

    #2
    Re: python2.4 generator expression &gt; python2.3 list expression

    snacktime wrote:[color=blue]
    > I need to convert a generator expression to a list expression so it
    > will work under python 2.3.
    >
    > I rewrote this:
    >
    > for c in range(128):
    > even_odd = (sum(bool(c & 1<<b) for b in range(8))) & 1
    >
    > As this:
    >
    > for c in range(128):
    > bo = [bool(c & 1<<b) for b in range(8)]
    > even_odd = sum(bo) & 1
    >
    > Seems to work, is there a better way to do this?[/color]

    Well, if you were happy with your generator expression, you can use
    almost exactly the same syntax:

    for c in range(128):
    even_odd = (sum([bool(c & 1<<b) for b in range(8)])) & 1

    No need for the 'bo' variable...

    STeVe

    Comment

    • Michael Hoffman

      #3
      Re: python2.4 generator expression &gt; python2.3 list expression

      snacktime wrote:[color=blue]
      > I need to convert a generator expression to a list expression so it
      > will work under python 2.3.
      >
      > I rewrote this:
      >
      > for c in range(128):
      > even_odd = (sum(bool(c & 1<<b) for b in range(8))) & 1
      >
      > As this:
      >
      > for c in range(128):
      > bo = [bool(c & 1<<b) for b in range(8)]
      > even_odd = sum(bo) & 1
      >
      >
      > Seems to work, is there a better way to do this?[/color]

      If you want to keep it as a generator that doesn't build a list
      in memory, you can use itertools:

      import itertools

      for c in range(128):
      def _even_odd_func( b): return bool(c & 1<<b)
      even_odd = (sum(itertools. imap(_even_odd_ func, xrange(8)))) & 1

      The fact that you used range() instead of xrange() indicates that
      you may not care about this, though. ;-)
      --
      Michael Hoffman

      Comment

      • Peter Otten

        #4
        Re: python2.4 generator expression &gt; python2.3 list expression

        snacktime wrote:
        [color=blue]
        > I need to convert a generator expression to a list expression so it
        > will work under python 2.3.
        >
        > I rewrote this:
        >
        > for c in range(128):
        > even_odd = (sum(bool(c & 1<<b) for b in range(8))) & 1
        >
        > As this:
        >
        > for c in range(128):
        > bo = [bool(c & 1<<b) for b in range(8)]
        > even_odd = sum(bo) & 1
        >
        >
        > Seems to work, is there a better way to do this?[/color]

        Summing over zeros seems pointless, so
        [color=blue][color=green][color=darkred]
        >>> for c in range(128):[/color][/color][/color]
        .... print len([1 for b in range(8) if c & 1 << b]) & 1,
        ....
        0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 1 0 0 1 0 1
        1 0 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 1 1 0
        1 0 0 1 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0
        0 1 0 1 1 0 0 1 1 0 1 0 0 1

        The same simplification works for genexps, but you have to use sum() there
        instead of len(). Another optimization would be to precalculate the
        bitmasks [1 << b for b in range(8)] outside the loop.

        Peter

        Comment

        • Dan Sommers

          #5
          Re: python2.4 generator expression &gt; python2.3 list expression

          On Sun, 20 Feb 2005 20:56:52 -0800,
          snacktime <snacktime@gmai l.com> wrote:
          [color=blue]
          > I need to convert a generator expression to a list expression so it
          > will work under python 2.3.[/color]
          [color=blue]
          > I rewrote this:[/color]
          [color=blue]
          > for c in range(128):
          > even_odd = (sum(bool(c & 1<<b) for b in range(8))) & 1[/color]
          [color=blue]
          > As this:[/color]
          [color=blue]
          > for c in range(128):
          > bo = [bool(c & 1<<b) for b in range(8)]
          > even_odd = sum(bo) & 1[/color]

          [color=blue]
          > Seems to work, is there a better way to do this?[/color]

          for c in range( 128 ):
          even_odd = 0
          print '%3d' % c,
          while c:
          c &= c - 1
          even_odd = not even_odd
          print int( even_odd )

          Okay, so your inner loop is only counting to 8, but IMO this is a good
          example of how to use a better algorithm instead of optimizing the code
          of a naïve one. My inner loop only iterates over 1-bits.

          "Better," of course is all relative. Your algorithm obviously counts
          bits in an integer. My algorithm is less clear at first glance (and
          even second and third glance), but nearly idiomatic to those of us who
          spent lots of time writing embedded assembly code.

          If you have the space to spare, a lookup table (pre-calculated or
          created during your program's initialization) is probably the best way
          to go.

          Regards,
          Dan

          --
          Dan Sommers
          <http://www.tombstoneze ro.net/dan/>
          Never play leapfrog with a unicorn.

          Comment

          • Christos TZOTZIOY Georgiou

            #6
            Re: python2.4 generator expression &gt; python2.3 list expression

            On 21 Feb 2005 06:48:19 -0500, rumours say that Dan Sommers <me@privacy.net >
            might have written:

            [snip: snacktime posts code to count bits]
            [color=blue][color=green]
            >> Seems to work, is there a better way to do this?[/color][/color]

            [Dan][color=blue]
            >for c in range( 128 ):
            > even_odd = 0
            > print '%3d' % c,
            > while c:
            > c &= c - 1
            > even_odd = not even_odd
            > print int( even_odd )[/color]

            Just for the sake of people who haven't messed with bit manipulation in C or
            assembly, the effect of

            c &= c - 1

            is to reset the rightmost (less significant) '1' bit of a number (ie change it
            to '0').
            --
            TZOTZIOY, I speak England very best.
            "Be strict when sending and tolerant when receiving." (from RFC1958)
            I really should keep that in mind when talking with people, actually...

            Comment

            • Bryan

              #7
              Re: python2.4 generator expression &gt; python2.3 list expression

              Christos TZOTZIOY Georgiou wrote:[color=blue]
              > On 21 Feb 2005 06:48:19 -0500, rumours say that Dan Sommers <me@privacy.net >
              > might have written:
              >
              > [snip: snacktime posts code to count bits]
              >
              >[color=green][color=darkred]
              >>>Seems to work, is there a better way to do this?[/color][/color]
              >
              >
              > [Dan]
              >[color=green]
              >>for c in range( 128 ):
              >> even_odd = 0
              >> print '%3d' % c,
              >> while c:
              >> c &= c - 1
              >> even_odd = not even_odd
              >> print int( even_odd )[/color]
              >
              >
              > Just for the sake of people who haven't messed with bit manipulation in C or
              > assembly, the effect of
              >
              > c &= c - 1
              >
              > is to reset the rightmost (less significant) '1' bit of a number (ie change it
              > to '0').[/color]

              i tried c &= c - 1 but i'm not getting the least significant or rightmost bit
              reset to zero. am i misunderstandin g something?
              [color=blue][color=green][color=darkred]
              >>> 2 & 1 # 2 = 0x10; reset right most would be 0x10[/color][/color][/color]
              0[color=blue][color=green][color=darkred]
              >>> 10 & 9 # 10 = 0x1010; reset right most would be 0x1010[/color][/color][/color]
              8

              bryan

              Comment

              • Duncan Booth

                #8
                Re: python2.4 generator expression &gt; python2.3 list expression

                Bryan wrote:
                [color=blue][color=green]
                >> is to reset the rightmost (less significant) '1' bit of a number (ie
                >> change it to '0').[/color]
                >
                > i tried c &= c - 1 but i'm not getting the least significant or
                > rightmost bit reset to zero. am i misunderstandin g something?
                >[color=green][color=darkred]
                > >>> 2 & 1 # 2 = 0x10; reset right most would be 0x10[/color][/color]
                > 0[color=green][color=darkred]
                > >>> 10 & 9 # 10 = 0x1010; reset right most would be 0x1010[/color][/color]
                > 8[/color]

                The difference between the original "reset the rightmost '1' bit", and your
                interpretation: "reset the rightmost bit" is the "'1'".

                The rightmost bit that is set is reset. So 0x10 -> 0, and 0x1010 -> 0x1000.

                If you want to extract the least significant set bit from a number 'x' you
                can use (x&-x):
                [color=blue][color=green][color=darkred]
                >>> x = 0xab4
                >>> while x:[/color][/color][/color]
                print hex(x&-x), hex(x)
                x ^= (x&-x)


                0x4 0xab4
                0x10 0xab0
                0x20 0xaa0
                0x80 0xa80
                0x200 0xa00
                0x800 0x800[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                (but don't try this if x is negative: it works but never terminates).

                Comment

                • Brian Beck

                  #9
                  Re: python2.4 generator expression &gt; python2.3 list expression

                  Duncan Booth wrote:[color=blue]
                  > The difference between the original "reset the rightmost '1' bit", and your
                  > interpretation: "reset the rightmost bit" is the "'1'".
                  >
                  > The rightmost bit that is set is reset. So 0x10 -> 0, and 0x1010 -> 0x1000.
                  >
                  > If you want to extract the least significant set bit from a number 'x' you
                  > can use (x&-x):[/color]

                  My interpretation of Bryan's (mis?)interpret ation (heh) was that since
                  in the numbers 2 and 10 (as in his examples), the least significant bit
                  was already 0, performing an operation that set it to 0 should result in
                  the number unchanged. As his tests show, this is not the case. This is
                  because the operation works only if the least significant bit actually
                  NEEDS to be unset. To zero the least significant bit unconditionally , we
                  can use:

                  x &= ~1

                  --
                  Brian Beck
                  Adventurer of the First Order

                  Comment

                  • Bryan

                    #10
                    Re: python2.4 generator expression &gt; python2.3 list expression

                    Duncan Booth wrote:[color=blue]
                    > Bryan wrote:
                    >
                    >[color=green][color=darkred]
                    >>>is to reset the rightmost (less significant) '1' bit of a number (ie
                    >>>change it to '0').[/color]
                    >>
                    >>i tried c &= c - 1 but i'm not getting the least significant or
                    >>rightmost bit reset to zero. am i misunderstandin g something?
                    >>
                    >>[color=darkred]
                    >>>>>2 & 1 # 2 = 0x10; reset right most would be 0x10[/color]
                    >>
                    >>0
                    >>[color=darkred]
                    >>>>>10 & 9 # 10 = 0x1010; reset right most would be 0x1010[/color]
                    >>
                    >>8[/color]
                    >
                    >
                    > The difference between the original "reset the rightmost '1' bit", and your
                    > interpretation: "reset the rightmost bit" is the "'1'".
                    >
                    > The rightmost bit that is set is reset. So 0x10 -> 0, and 0x1010 -> 0x1000.
                    >
                    > If you want to extract the least significant set bit from a number 'x' you
                    > can use (x&-x):
                    >
                    >[color=green][color=darkred]
                    >>>>x = 0xab4
                    >>>>while x:[/color][/color]
                    >
                    > print hex(x&-x), hex(x)
                    > x ^= (x&-x)
                    >
                    >
                    > 0x4 0xab4
                    > 0x10 0xab0
                    > 0x20 0xaa0
                    > 0x80 0xa80
                    > 0x200 0xa00
                    > 0x800 0x800
                    >
                    >
                    > (but don't try this if x is negative: it works but never terminates).[/color]

                    thanks duncan... you're right, i did intrepret this as "reset the rightmost bit"
                    instead of "reset the rightmost '1' bit". and i must have read what christos
                    wrote 100 times!!!

                    bryan

                    Comment

                    • Terry Reedy

                      #11
                      Re: python2.4 generator expression &gt; python2.3 list expression


                      "Christos TZOTZIOY Georgiou" <tzot@sil-tec.gr> wrote in message
                      news:0ioj11dsgq hatqc3d7ldeb35r ta6d9fk69@4ax.c om...[color=blue]
                      > On 21 Feb 2005 06:48:19 -0500, rumours say that Dan Sommers
                      > <me@privacy.net >[color=green]
                      >>for c in range( 128 ):
                      >> even_odd = 0
                      >> print '%3d' % c,
                      >> while c:
                      >> c &= c - 1
                      >> even_odd = not even_odd
                      >> print int( even_odd )[/color]
                      >
                      > Just for the sake of people who haven't messed with bit manipulation in C
                      > or
                      > assembly, the effect of
                      > c &= c - 1
                      > is to reset the rightmost (less significant) '1' bit of a number (ie
                      > change it
                      > to '0').[/color]

                      Cute. I tried it a few times until I saw why it works. But it is also
                      dangerous (within a loop like the above) in a language like current Python
                      (and unlike C/assembler) in which the binary representation of -1 is
                      effectively a left infinite string of '1's: ...1111111111

                      Terry J. Reedy



                      Comment

                      • Christos TZOTZIOY Georgiou

                        #12
                        Re: python2.4 generator expression &gt; python2.3 list expression

                        On Mon, 21 Feb 2005 10:55:05 -0800, rumours say that Bryan <belred@gmail.c om>
                        might have written:


                        [I][color=blue][color=green][color=darkred]
                        >>>>is to reset the rightmost (less significant) '1' bit of a number (ie
                        >>>>change it to '0').[/color][/color][/color]

                        [bryan][color=blue][color=green][color=darkred]
                        >>>i tried c &= c - 1 but i'm not getting the least significant or
                        >>>rightmost bit reset to zero. am i misunderstandin g something?
                        >>>
                        >>>
                        >>>>>>2 & 1 # 2 = 0x10; reset right most would be 0x10[/color][/color][/color]

                        <snip>

                        [Duncan][color=blue][color=green]
                        >> The difference between the original "reset the rightmost '1' bit", and your
                        >> interpretation: "reset the rightmost bit" is the "'1'".
                        >>
                        >> The rightmost bit that is set is reset. So 0x10 -> 0, and 0x1010 -> 0x1000.[/color][/color]

                        <snip>

                        [color=blue]
                        >thanks duncan... you're right, i did intrepret this as "reset the rightmost bit"
                        >instead of "reset the rightmost '1' bit". and i must have read what christos
                        >wrote 100 times!!![/color]

                        Don't worry, Bryan, I'm probably more to blame, since I have this tendency to
                        interject parenthesized sub-sentences all over my paragraphs, that probably
                        confuse more than clarify things ( self.remind(pro se is not code) :).

                        Perhaps I should crosspost my replies (esp. the ones with nested parentheses) to
                        comp.lang.lisp ...
                        --
                        TZOTZIOY, I speak England very best.
                        "Be strict when sending and tolerant when receiving." (from RFC1958)
                        I really should keep that in mind when talking with people, actually...

                        Comment

                        • Duncan Booth

                          #13
                          Re: python2.4 generator expression &gt; python2.3 list expression

                          Dan Sommers wrote:
                          [color=blue][color=green]
                          >> Seems to work, is there a better way to do this?[/color]
                          >
                          > for c in range( 128 ):
                          > even_odd = 0
                          > print '%3d' % c,
                          > while c:
                          > c &= c - 1
                          > even_odd = not even_odd
                          > print int( even_odd )
                          >
                          > Okay, so your inner loop is only counting to 8, but IMO this is a good
                          > example of how to use a better algorithm instead of optimizing the code
                          > of a naïve one. My inner loop only iterates over 1-bits.
                          >[/color]

                          Here's yet another way to achieve the same results. This version doesn't
                          iterate over any bits at all:
                          [color=blue][color=green][color=darkred]
                          >>> import operator
                          >>> parity = [ False ]
                          >>> for i in range(7):[/color][/color][/color]
                          parity += map(operator.no t_, parity)

                          And if you want the same output:
                          [color=blue][color=green][color=darkred]
                          >>> for even_odd in parity:[/color][/color][/color]
                          print int(even_odd)

                          Comment

                          • Dan Sommers

                            #14
                            Re: python2.4 generator expression &gt; python2.3 list expression

                            On 22 Feb 2005 09:14:50 GMT,
                            Duncan Booth <duncan.booth@i nvalid.invalid> wrote:
                            [color=blue]
                            > Here's yet another way to achieve the same results. This version doesn't
                            > iterate over any bits at all:[/color]
                            [color=blue][color=green][color=darkred]
                            >>>> import operator
                            >>>> parity = [ False ]
                            >>>> for i in range(7):[/color][/color]
                            > parity += map(operator.no t_, parity)[/color]

                            Very clever! :-)

                            Picking a nit, that version iterates over *two* sets of bits. The "for"
                            loop over each possible bit in the input values. The "map" function
                            over the parity bits accumulated up to that point. And the "+="
                            operator over those same bits again. Make that *three* sets of bits.

                            I stand humbled.

                            Regards,
                            Dan

                            --
                            Dan Sommers
                            <http://www.tombstoneze ro.net/dan/>
                            μ₀ × ε₀ × c² = 1

                            Comment

                            Working...