Why is one substitution strategy slower than another?

So this page about memories is curious to me. I conducted my own tests.

1) Mutable default dictionary:

%%timeit
def fibo(n, dic={}) :
    if n not in dic :
        if n in (0,1) :
            dic[n] = 1
        else :
            dic[n] = fibo(n-1)+fibo(n-2)
    return dic[ n ]
fibo(30)

Of:

100000 loops, best of 3: 18.3 µs per loop

2) The same idea, but on the principle of "easier to ask for forgiveness than permission":

In [21]:

%%timeit
def fibo(n, dic={}) :
    try :
        return dic[n]
    except :
        if n in (0,1) :
            dic[n] = 1
        else :
            dic[n] = fibo(n-1)+fibo(n-2)
        return dic[ n ]
fibo(30)

Of:

10000 loops, best of 3: 46.8 µs per loop

My questions

  • Why is 2) so slow compared to 1)?

Edit

As @kevin suggests in the comments, I got the decorator completely wrong, so I deleted it. The rest is still valid! (Hope)

+4
source share
2 answers

Catching exception means stack trace, which can be very expensive:

https://docs.python.org/2/faq/design.html#how-fast-are-exceptions

:

  • try ... finally
  • try ... except, ,

, .

+6

(n not in dic:, insertion dic[n] = return dic[n]). ( dic[n] =, insertion dic[n] = return dic[n]), .

, , - , , , , , .

, memoization , - , , . , , - .

Version1:

def fibo(n, dic={}) :
    if n not in dic :
        if n in (0,1) :
            dic[n] = 1
        else :
            dic[n] = fibo(n-1)+fibo(n-2)
    return dic[ n ]

for i in range(10000):
    fibo(i)

Version2:

def fibo(n, dic={}) :
    try :
        return dic[n]
    except :
        if n in (0,1) :
            dic[n] = 1
        else :
            dic[n] = fibo(n-1)+fibo(n-2)
        return dic[ n ]

for i in range(10000):
    fibo(i)

:

C:\Users\Bartek\Documents\Python > python -m timeit - "import version1"
1000000 , 3: 1.64 usec

C:\Users\Bartek\Documents\Python > python -m timeit -" import version2 "
1000000 , 3: 1.6 usec

, , , , .

0

All Articles