4.Python 闭包函数示例

#1. 递归函数调用
#递归函数调用
def fibonacci(n):
    '''fibonacci function'''
    if n<=1:
        return 1
    return fibonacci(n-1)+fibonacci(n-2)
fibonacci(50)#迭代次数太多导致程序崩盘,长时间没有返回

#2.使用Cache记录已计算结果,如有则直接返回,没有则添加

def fibonacci1(n,cache=None):
    if n<=1:
        return 1
    if cache==None:
        cache={}
    if n in cache:
        return cache[n]
    else:
        cache[n]=fibonacci1(n-1,cache)+fibonacci1(n-2,cache)
        return cache[n]

fibonacci1(100)
#计算速度很快

#计算结果: 573147844013817084101

#3.#创建闭包装饰器
def collect(func):
    cache={}
    def wrap(*args):
        if args not in cache:
            cache[args]=func(*args)
        return cache[args]
    return wrap

@collect
def fibonacci2(n):
    if n<=1:
        return 1
    return fibonacci2(n-1)+fibonacci2(n-2)
fibonacci2(100)# 或使用 fibonacci2=collect(fibonacci2)

#计算结果: 573147844013817084101

#4.#如何跳过Wrap将function的属性显示出来

fibonacci.__doc__ #结果为 'fibonacci function'

fibonacci.__name__ #结果为 'fibonacci'

但是 fibonacci2.__name__ 结果却是 'wrap'

可以使用 functiontools中的装饰器wraps装饰内部 包裹函数,将原函数属性传递到Wrap函数里

#4.1 from functools import wraps

#4.2 用wraps装饰器装饰闭包函数,@wraps(func)

#打印fibonacci2.__name__结果为fibonacci2

#5.#如何判断函数传入的参数类型是否正确

from inspect import signature
def typeassert(*ty_args,**ty_kargs):
    def decorator(func):
        sig=signature(func)
        print(sig)
        btypes=sig.bind_partial(*ty_args,**ty_kargs).arguments
        #btypes=OrderedDict([('a', <class 'int'>), ('b', <class 'int'>), ('c', <class 'int'>)])
        print(btypes)
        def wrapper(*args,**kargs):
            #print(sig.bind(*args,**kargs).arguments.items())
            #sig.bind(*args,**kargs).arguments.items() =odict_items([('a', 1), ('b', 9), ('c', 3)])
            for name,obj in sig.bind(*args,**kargs).arguments.items():
                if name in btypes:
                    if not isinstance(obj,btypes[name]):
                        raise TypeError('{0} must be {1}'.format(name,btypes[name]))
            return func(*args,**kargs)
        return wrapper
    return decorator
@typeassert(int,int,int)#也可以只定义前两个(int,int)
def f(a,b,c):
    print('{},{},{}'.format(a,b,c))
f(1,9,3)

#结果1,9,3

f('a1','bb','cc')

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-66-61585f180c14> in <module>
     21     print('{},{},{}'.format(a,b,c))
     22 f(1,9,('a3','b5'))
---> 23 f('a1','bb','cc')

<ipython-input-66-61585f180c14> in wrapper(*args, **kargs)
     13                 if name in btypes:
     14                     if not isinstance(obj,btypes[name]):
---> 15                         raise TypeError('{0} must be {1}'.format(name,btypes[name]))
     16             return func(*args,**kargs)
     17         return wrapper

TypeError: a must be <class 'int'>

#6.#如何统计函数运行时间

import time
import logging

def warn(timeout):
    timeout=[timeout]
    def decorator(func):
        def wrapper(*args,**kargs):
            start=time.time()
            res=func(*args,**kargs)
            used=time.time()-start
            if used > timeout[0]:
                msg='{}: {}>{}'.format(func.__name__,used,timeout[0])
                logging.warn(msg)
                print(msg)
            return res
        def setTimeout(k):
            #nonlocal timeout
            timeout[0]=k
        wrapper.setTimeout=setTimeout
        return wrapper
    return decorator

from random import randint

@warn(1.5)
def test():
    print('in test')
    while randint(0,1):
        time.sleep(0.7)

for _ in range(30):
    test()

'''#结果显示
in test
in test
in test
in test
D:\software\Anaconda1\lib\site-packages\ipykernel_launcher.py:13: DeprecationWarning: The 'warn' function is deprecated, use 'warning' instead
  del sys.path[0]
WARNING:root:test: 2.802633285522461>1.5
'''

 

 

 

#此博客为本人学习Python教程文档,并通过Jupiter验证后结果.不为盈利之用途

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值