Weird try-except vs if behavior

Terry Reedy tjreedy at udel.edu
Fri Oct 15 13:16:57 EDT 2010


On 10/15/2010 3:11 AM, Ryan Kelly wrote:
> On Thu, 2010-10-14 at 22:43 -0700, James Matthews wrote:
>> Hi,
>>
>> I have this code http://gist.github.com/627687 (I don't like pasting
>> code into the mailing list).
>
> Yes, but it makes it harder to discuss the ode and makes the archive
> that much more useless.  It's only a couple of lines, here ya go:
>
>    def tryway():
>        try:
>            while True:
>                alist.pop()
>        except IndexError:
>            pass
>
>
>    def ifway():
>        while True:
>            if blist == []:
>                break
>            else:
>                blist.pop()
>
>    if __name__=='__main__':
>        alist = range(1000)
>        blist = range(1000)
>        from timeit import Timer
>        print "Testing Try"
>        tr = Timer("tryway()","from __main__ import tryway")
>        print tr.timeit()
>        print "Testing If"
>        ir = Timer("ifway()","from __main__ import ifway")
>        print ir.timeit()
>
>
>>   I am wondering why the try except is taking longer. I assume that if
>> the IF statement checks every iteration of the loop (1000 times)
>> shouldn't it be slower?
>
> You're not measuring what you think.  The way you've structured your
> code, "alist" and "blist" are module globals.
>
> Timeit will call the "tryway" function one million times in a loop.  The
> first time it works as you expect, popping each element off of "alist"
> in turn.  On the other 999999 executions, "alist" is already empty
> (having been emptied by the first execution) and the IndexError is
> raised immediately.
>
> Likewise for the execution of "ifway".
>
> So what you're really measuring is the overhead of catching an exception
> versus testing a condition for an *empty* list - no surprise that the
> conditional version is faster!
>
> If you re-initialise the list at the beginning of each function, the
> try-based version is faster as you expect.  I.e.:
>
>    def tryway():
>        alist = range(1000)
>        try:
>            while True:
>                alist.pop()
>        except IndexError:
>            pass
>
> I get the following times for a thousand iterations (not waiting around
> for a million!)
>
>    Testing Try
>    0.224129915237
>    Testing If
>    0.300312995911

Excellent answer, nothing to add.
-- 
Terry Jan Reedy




More information about the Python-list mailing list