Counting iterations

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

    #1

    Counting iterations

    Is there a better way to count iterations that this?:

    pets = 0
    for i in pets:
    pets += 1
    print "pet" + "#" + pets

    Thanks,
    Derek Basch

  • Steven Bethard

    #2
    Re: Counting iterations

    Derek Basch wrote:[color=blue]
    > Is there a better way to count iterations that this?:
    >
    > pets = 0
    > for i in pets:
    > pets += 1
    > print "pet" + "#" + pets[/color]

    for i, pet in enumerate(pets) :
    print 'pet#%i' % (i + 1)

    STeVe

    Comment

    • Will McGugan

      #3
      Re: Counting iterations

      Derek Basch wrote:[color=blue]
      > Is there a better way to count iterations that this?:
      >
      > pets = 0
      > for i in pets:
      > pets += 1
      > print "pet" + "#" + pets
      >[/color]

      You can use 'enumerate' to get the index, but the code above wont work -
      you are trying to iterate over a non-sequence.

      Will McGugan

      --
      "".join( [ {'@':'@','.':'. '}.get(c,None) or chr(97+((ord(c)-97)+13)%26)
      for c in "jvyy@jvyyzptht na.pbz" ] )

      Comment

      • Derek Basch

        #4
        Re: Counting iterations

        ooops you are right. Should have been:

        pets = ["cat", "dog", "bird"]
        num_pets = 0
        for i in pets:
        num_pets += 1
        print "pet" + "#" + num_pets

        That's the problem with one offs. I don't read them :).

        Comment

        • Fredrik Lundh

          #5
          Re: Counting iterations

          Derek Basch wrote:
          [color=blue]
          > ooops you are right. Should have been:
          >
          > pets = ["cat", "dog", "bird"]
          > num_pets = 0
          > for i in pets:
          > num_pets += 1
          > print "pet" + "#" + num_pets[/color]

          Traceback (most recent call last):
          File "example.py ", line 5, in ?
          print "pet" + "#" + num_pets
          TypeError: cannot concatenate 'str' and 'int' objects

          </F>



          Comment

          • runes

            #6
            Re: Counting iterations

            You should avoid the "a" + "b" + "c" -kind of concatenation. As strings
            at immutable in Python you actually makes copies all the time and it's
            slow!

            The alternative used in Steven Bethard's example is preferable.

            Comment

            • Andrew Dalke

              #7
              Re: Counting iterations

              runes wrote:[color=blue]
              > You should avoid the "a" + "b" + "c" -kind of concatenation. As strings
              > at immutable in Python you actually makes copies all the time and it's
              > slow![/color]

              The OP wrote

              print "pet" + "#" + num_pets

              (properly str(num_pets) )

              You recommended the "alternativ e used in Steven Bethard's example"

              print 'pet#%i' % (i + 1)

              because "it's slow". I disagree, it isn't for this code.
              It's comparable in performance to interpolation and most
              of the time is spent in converting int -> string. Indeed
              if the object to be merged is a string then the addition
              version is faster than interpolation.

              Here's the details.

              The string concatenation performance that you're
              talking about doesn't hit until there are multiple
              appends to the same string, where "multiple" is rather
              more than 2. The advice usually applies to things like

              text = ""
              for line in open(filename, "U"):
              text += line

              which is much slower than, say
              lines = []
              for line in open(filename, "U")
              lines.append(li ne)
              text = "".join(lin es)

              or the more modern
              text = "".join(open(fi lename, "U"))

              to say nothing of
              text = open(filename, "U").read() :)

              Anyway, to get back to the example at hand,
              consider what happens in

              "pet#%i" % (i+1)

              (NOTE: most times that's written %d instead of %i)

              The run-time needs to parse the format string
              and construct a new string from the components.
              Internally it does the same thing as

              "pet#" + str(i+1)

              except that it's done at the C level instead
              Python and the implementation overallocates
              100 bytes so there isn't an extra allocation
              in cases like this.

              Personally I would expect the "%" code to be
              about the same performance as the "+" code.


              Of course the real test is in the timing.
              Here's what I tried. NOTE: I reformatted by
              hand to make it more readable. Line breaks and
              the \ continuation character may have introduced
              bugs.

              First, the original code along with the 'str()'
              correction.

              % python /usr/local/lib/python2.3/timeit.py -s \
              'pets = ["cat", "dog", "bird"]' \
              'num_pets=0' 'for pet in pets:' \
              ' num_pets += 1' \
              ' s="pet" + "#" + str(num_pets)'
              100000 loops, best of 3:
              14.5 usec per loop


              There's no need for the "pet" + "#" so I'll
              turn that into "pet#"

              % python /usr/local/lib/python2.3/timeit.py -s \
              'pets = ["cat", "dog", "bird"]' \
              'num_pets=0' \
              'for pet in pets:' \
              ' num_pets += 1' \
              ' s="pet#" + str(num_pets)'
              100000 loops, best of 3: 12.8 usec per loop

              That's 1.3 extra usecs.

              By comparison here's the "%" version.

              % python /usr/local/lib/python2.3/timeit.py -s \
              'pets = ["cat", "dog", "bird"]'\
              'num_pets=0' \
              'for pet in pets:' \
              ' num_pets += 1' \
              ' s="pet#%s" % num_pets'
              100000 loops, best of 3: 10.8 usec per loop

              I'm surprised that it's that much faster - a
              good 2 microseconds and that isn't the only
              code in that loop.

              But both the "%" and "+" solutions need to
              convert the number into a string. If I
              use an existing string I find

              % python /usr/local/lib/python2.3/timeit.py -s \
              'pets = ["cat", "dog", "bird"]' \
              'num_pets=0' \
              'for pet in pets:' \
              ' num_pets += 1' \
              ' s="pet#" + pet'
              100000 loops, best of 3: 4.62 usec per loop

              So really most of the time - about 8 usec - is
              spent in converting int -> string and the
              hit for string concatenation or interpolation
              isn't as big a problem.

              Compare with the string interpolation form
              of the last version

              % python /usr/local/lib/python2.3/timeit.py -s \
              'pets = ["cat", "dog", "bird"]' \
              'num_pets=0' 'for pet in pets:' \
              ' num_pets += 1' \
              ' s="pet#%s" % pet' \
              100000 loops, best of 3: 7.55 usec per loop


              In this case you can see that the % version is
              slower (by 2usec) than the + version.

              I therefore disagree with the idea that simple
              string concatenation is always to be eschewed
              over string interpolation.

              Andrew
              dalke@dalkescie ntific.com

              Comment

              • Steven Bethard

                #8
                Re: Counting iterations

                Andrew Dalke wrote:[color=blue]
                > "pet#%i" % (i+1)
                >
                > (NOTE: most times that's written %d instead of %i)[/color]

                Any reason to prefer %d over %i? The library reference seems to suggest
                that they're the same thing[1]. I've typically used %i since I can
                remember it from the int type, like I can remember %f from the float
                type. Is there any reason not to?

                STeVe

                [1] http://docs.python.org/lib/typesseq-strings.html

                Comment

                • runes

                  #9
                  Re: Counting iterations


                  [Andrew Dalke][color=blue]
                  > I therefore disagree with the idea that simple
                  > string concatenation is always to be eschewed
                  > over string interpolation.[/color]

                  Andrew, what you write makes sense. I've never really tested it, just
                  read it several places, fx here:


                  Comment

                  • Derek Basch

                    #10
                    Re: Counting iterations

                    Interesting stuff Andrew. I do generally avoid string concantination
                    for the reason listed in the Python Performance Tips but your analysis
                    kinda puts that in question. Such a dense discussion for me just trying
                    to find the enumerate() function :). I guess that is why the python
                    list is so great. You guys always rip my code apart and correct my
                    style. Even if it is just a stupid one off example.

                    Thanks everyone,
                    Derek Basch

                    Comment

                    • Terry Reedy

                      #11
                      Re: Counting iterations


                      "runes" <rune.strand@gm ail.com> wrote in message
                      news:1113114411 .612323.187860@ g14g2000cwa.goo glegroups.com.. .[color=blue]
                      >
                      > [Andrew Dalke][color=green]
                      >> I therefore disagree with the idea that simple
                      >> string concatenation is always to be eschewed
                      >> over string interpolation.[/color][/color]

                      String cat (+) is fine for joining a few short strings.
                      [color=blue]
                      > Andrew, what you write makes sense. I've never really tested it, just
                      > read it several places, fx here:
                      > http://www.python.org/moin/PythonSpe...Tips#stringcat[/color]

                      This is about making long strings in situations where performance is an
                      issue.

                      Terry J. Reedy



                      Comment

                      • Andrew Dalke

                        #12
                        Re: Counting iterations

                        Derek Basch wrote:[color=blue]
                        > Interesting stuff Andrew. I do generally avoid string concantination
                        > for the reason listed in the Python Performance Tips but your analysis
                        > kinda puts that in question.[/color]

                        Thanks.

                        It was interesting for me to. I hadn't looked at the implementation
                        for string % before and was rather surprised to find that it
                        overallocates 100 bytes to reduce the number of allocs done. It's
                        simpler than the implementation I considered.

                        Andrew
                        dalke@dalkescie ntific.com

                        Comment

                        Working...