#known = {0:0, 1:1}
#def fibonacci(n):
#    assert(n>=0), 'n must be >= 0'
#    if n in known:
#        return known[n]
#    res = fibonacci(n-1) + fibonacci(n-2)
#    known[n] = res 
#    return res



import functools 
def memoize(fn):
    known = dict()

    @functools.wraps(fn)
    def memoizer(*args):
        if args not in known:
            known[args] = fn(*args)
        return known[args]
    return memoizer

@memoize
def fibonacci(n):
    '''返回斐波那契数列的第n个数'''
    assert(n >= 0), 'n must be >= 0'

    # 装饰器将known=dict()语句插入到这里
    # 并包装自身,进来的n运行装饰器的代码
    # 如果n不在字典known中,再运行此函数fn
    return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2)



@memoize
def nsum(n):
    '''返回前n个数字的和'''
    # func.__doc__返回函数里的'''内容'''
    assert(n >= 0), 'n must be >= 0'
    return 0 if n == 0 else n + nsum(n-1)

if __name__ == '__main__':
    from timeit import Timer
    measure = [ {'exec':'fibonacci(100)','import':'fibonacci','func':fibonacci},
            {'exec':'nsum(200)','import':'nsum','func':nsum}]
    for m in measure:
        # Timer的第一个参数是字符串,接收的是python命令
        # 返回两条语句执行时间差
        t = Timer('{}'.format(m['exec']),'from __main__ import {}'.format(m['import']))
        print ('name:{},doc:{},executing:{},time:{}'.format(m['func'].__name__, m['func'].__doc__, m['exec'], t.timeit()))
# func.__doc__返回函数里的'''内容'''