Python if vs try-except

前端 未结 7 1874
执笔经年
执笔经年 2020-12-05 23:16

I was wondering why the try-except is slower than the if in the program below.

def tryway():
    try:
        while True:
            alist.pop()
    except         


        
相关标签:
7条回答
  • 2020-12-05 23:59

    Not sure but I think it's something like this: the while true follow the normal instruction line which means the processor can pipeline and do all sorts of nice things. Exceptions jump straight through all that so the VM need to handle it specially, and that takes time.

    0 讨论(0)
  • 2020-12-05 23:59

    Just thought to toss this into the mix: I tried the following script below which seems to suggest that handling an exception is slower than handling an else statement:

    import time
    
    n = 10000000
    l = range(0, n)
    t0 = time.time()
    for i in l:
        try:
            i[0]
        except:
            pass
    t1 = time.time()
    for i in l:
        if type(i) == list():
            print(i)
        else:
            pass
    t2 = time.time()
    print(t1-t0)
    print(t2-t1)
    

    gives:

    5.5908801555633545
    3.512694835662842
    

    So, (even though I know someone will likely comment upon the use of time rather than timeit), there appears to be a ~60% slow down using try/except in loops. So, perhaps better to go with if/else when going through a for loop of several billion items.

    0 讨论(0)
  • 2020-12-06 00:00

    Exception handling is generally slow in most languages. Most compilers, interpreters and VMs (that support exception handling) treat exceptions (the language idiom) as exceptions (uncommon). Performance optimization involves trade-offs and making exceptions fast would typically mean other areas of the language would suffer (either in performance or simplicity of design).

    At a more technical level, exceptions generally mean that the VM/interpretter (or the runtime execution library) has to save a bunch of state and begin pulling off all the state on the function call stack (called unwinding) up until the point where a valid catch (except) is found.

    Or looking at it from a different viewpoint, the program stops running when an exception occurs and a "debugger" takes over. This debugger searches back through the stack (calling function data) for a catch that matches the exception. If it finds one, it cleans things up and returns control to the program at that point. If it doesn't find one then it returns control to the user (perhaps in the form of an interactive debugger or python REPL).

    0 讨论(0)
  • 2020-12-06 00:14

    You're setting alist only once. The first call to "tryway" clears it, then every successive call does nothing.

    def tryway():
        alist = range(1000)
        try:
            while True:
                alist.pop()
        except IndexError:
            pass
    
    def ifway():
        alist = range(1000)
        while True:
            if alist == []:
                break
            else:
                alist.pop()
    if __name__=='__main__':
        from timeit import Timer
        print "Testing Try"
        tr = Timer("tryway()","from __main__ import tryway")
        print tr.timeit(10000)
        print "Testing If"
        ir = Timer("ifway()","from __main__ import ifway")
        print ir.timeit(10000)
    
    >>> Testing Try
    >>> 2.09539294243
    >>> Testing If
    >>> 2.84440898895
    
    0 讨论(0)
  • 2020-12-06 00:15

    If you are really interested in speed, both of your contestants could do with losing some weight.

    while True: is slower than while 1: -- True is a global "variable" which is loaded and tested; 1 is a constant and the compiler does the test and emits an unconditional jump.

    while True: is redundant in ifway. Fold the while/if/break together: while alist != []:

    while alist != []: is a slow way of writing while alist:

    Try this:

    def tryway2():
        alist = range(1000)
        try:
            while 1:
                alist.pop()
        except IndexError:
            pass
    
    def ifway2():
        alist = range(1000)
        while alist:
            alist.pop()
    

    `

    0 讨论(0)
  • 2020-12-06 00:17

    defensive programming requires that one test for conditions which are rare and/or abnormal, some of which during the course of a year or many years will not occur, thus in these circumstances perhaps try-except may be justified.

    0 讨论(0)
提交回复
热议问题