448,693 Members | 1,132 Online
Need help? Post your question and get tips & solutions from a community of 448,693 IT Pros & Developers. It's quick & easy.

# Counting iterations

 P: n/a Is there a better way to count iterations that this?: pets = 0 for i in pets: pets += 1 print "pet" + "#" + pets Thanks, Derek Basch Jul 18 '05 #1
11 Replies

 P: n/a Derek Basch wrote: Is there a better way to count iterations that this?: pets = 0 for i in pets: pets += 1 print "pet" + "#" + pets for i, pet in enumerate(pets): print 'pet#%i' % (i + 1) STeVe Jul 18 '05 #2

 P: n/a Derek Basch wrote: Is there a better way to count iterations that this?: pets = 0 for i in pets: pets += 1 print "pet" + "#" + pets 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 "jv**@jvyyzpthtna.pbz" ] ) Jul 18 '05 #3

 P: n/a 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 :). Jul 18 '05 #4

 P: n/a Derek Basch wrote: 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 Traceback (most recent call last): File "example.py", line 5, in ? print "pet" + "#" + num_pets TypeError: cannot concatenate 'str' and 'int' objects Jul 18 '05 #5

 P: n/a 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. Jul 18 '05 #6

 P: n/a runes wrote: 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 OP wrote print "pet" + "#" + num_pets (properly str(num_pets) ) You recommended the "alternative 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(line) text = "".join(lines) or the more modern text = "".join(open(filename, "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 da***@dalkescientific.com Jul 18 '05 #7

 P: n/a Andrew Dalke wrote: "pet#%i" % (i+1) (NOTE: most times that's written %d instead of %i) 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 Jul 18 '05 #8

 P: n/a [Andrew Dalke] I therefore disagree with the idea that simple string concatenation is always to be eschewed over string interpolation. 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 Jul 18 '05 #9

 P: n/a 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 Jul 18 '05 #10

 P: n/a "runes" wrote in message news:11**********************@g14g2000cwa.googlegr oups.com... [Andrew Dalke] I therefore disagree with the idea that simple string concatenation is always to be eschewed over string interpolation. String cat (+) is fine for joining a few short strings. 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 This is about making long strings in situations where performance is an issue. Terry J. Reedy Jul 18 '05 #11

 P: n/a Derek Basch wrote: 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. 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 da***@dalkescientific.com Jul 18 '05 #12

### This discussion thread is closed

Replies have been disabled for this discussion.