lru_cache singledispatch 2个标准库的装饰器

版权声明: https://blog.csdn.net/dashoumeixi/article/details/83758514

lru_cache  : 缓冲装饰器, 实际上自己可以用dict 来实现 .

singledispatch  : 相当于 c++ 中 stl 的函数特化(具体实例化) .  

如果有兴趣学c++ stl ,这里是我写的函数模版 : 函数模版 特化 模版指针 以及 类模版 具体化 特化 部分特化 友元

一个例子说明 lru_cache:


#一个普通装饰器
def clock(func):
    @functools.wraps(func)  #把原函数的__doc__ 以及 __name__ 复制进来
    def clocked(*args, **kwargs):
        '''clocked'''
        start  = time.perf_counter()
        res = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        name = func.__name__
        arg_str = ','.join(repr(arg) for arg in args)
        print("elapsed [%0.8fs] %s(%s) %s: " % (elapsed , name,arg_str,res))
        return res
    return clocked



#maxsize 存储多少条记录 , typed 把不同的类型区分
@functools.lru_cache(maxsize=128,typed=True) #可以把这行注释掉看看
@clock #装饰一下
def fibo(n):
    if n < 2:
        return n
    return fibo(n-2) + fibo(n-1)

if __name__ == "__main__":
    fibo(8)

#输出: 用了functools.lru_cache 后
elapsed [0.00000064s] fibo(0) 0: 
elapsed [0.00000064s] fibo(1) 1: 
elapsed [0.00005322s] fibo(2) 1: 
elapsed [0.00000096s] fibo(3) 2: 
elapsed [0.00007662s] fibo(4) 3: 
elapsed [0.00000096s] fibo(5) 5: 
elapsed [0.00009906s] fibo(6) 8: 
elapsed [0.00000096s] fibo(7) 13: 
elapsed [0.00012182s] fibo(8) 21: 

singledispatch  :  根据类型来调用某个函数实现 .

简单来说 c++ 的模版是一种通用类型,  跟某个具体类型( int , str ....) 没关系. 

一个c++的例子 : 

如果没学过stl的话, 请无视这些奇怪的东西, 只需要你专注 T 就行了.
T 代表某一种数据类型, 比方说 int , double ......

template <typename T> 
T compare(const T & a, const T & b)
{
    if(a >=b)
        return a;
    return b;
}

强调一下, 请无视这些 const(只读) 啊, &(引用) 这类符号 . python 都是引用.

现在比方说 你调用了 compare( 1, 2) 

此时编译器根据参数类型 int 将给你生成一个函数 int compare(const int&,const int&)

如果 : compare( 1.0 , 2.0 )  生成 double compare(const double&,const double&)

请注意.函数内部都不会改变


那么现在问题来了, 如果要进行字符串比较, 就不能使用这样的方式了把.

有一个东西叫特化(具体实例化):

//字符串比较 , 再次请无视这些参数,我知道很丑,很难看懂.总之这是一个字符串比较的特化版本

template <>  // <> 意味着特化
const char * compare(const char * const &a, const char * const & b)
{
    return strcmp(a,b);
}



现在当你使用 
const char * p1 = "123";
const char * p2 = "456";
compare(p1,p2); // 调用 compare(const char* const &,const char* const &);



#比方说有那么一个函数 . 需要根据类型来输出具体的情况,那么下面是一种实现
#这种方式比较方便,但难以维护 . 有可能上百个情况
def print_type(obj):
    if isinstance(obj,int):     #每次都用 isinstance 来判断
        print("int")
    elif isinstance(obj,str):
        print("str")
    else:
        print("other")





#下面是singledispatch
#特殊处理的函数名 我这里都是 _ , 请随意吧
#总的来说就是 根据不同的类型来调用不同的函数



@functools.singledispatch  #装饰之后,这个相当于一个模版了
def print_type2(obj):
    print("原始版本 type:%s" %type(obj))


@print_type2.register(str)  #特殊处理 str ,如果 obj 是str 将调用这个函数, 相当于c++的特化
def _(text):
    print("im str : %s , text:%s"  % (type(text),text))



@print_type2.register(int)  #处理 int的版本, 如果obj 是 int 调用此函数
def _(n):
    print("im int: %s , n:%s" % (type(n), n))


if __name__ == "__main__":
    print_type2(1)   #将调用_(n)



猜你喜欢

转载自blog.csdn.net/dashoumeixi/article/details/83758514
今日推荐