functools模块

全部方法

__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
           'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial',
           'partialmethod', 'singledispatch']

functools.partial ,functool.update_wrapper,functool.wraps在装饰器部分已经介绍了.

functools.cmp_to_key

将老式比较函数转换成key函数,用在接受key函数的方法中(such as sorted(), min(), max(), heapq.nlargest(), heapq.nsmallest(), itertools.groupby())

一个比较函数,接收两个参数,小于,返回负数,等于,返回0,大于返回整数

key函数,接收一个参数,返回一个表明该参数在期望序列中的位置

例如:

sorted(iterable, key=cmp_to_key(locale.strcoll))

  locale.strcoll是比较根据语言设置来比较字符串

functools.total_ordering(cls)

提供了对类对象更加丰富的比较,例如大于,小于,不小于,不大于
decorator类只需要实现__lt__(), __le__(), __gt__(), or __ge__()其中的一个,以及实现__eq__()。然后total_ordering会自动讲其他比较方法补全。
例如:
@total_ordering  
class Student:  
    def __eq__(self, other):  
        return ((self.lastname.lower(), self.firstname.lower()) ==  
                (other.lastname.lower(), other.firstname.lower()))  
    def __lt__(self, other):  
        return ((self.lastname.lower(), self.firstname.lower()) <  
                (other.lastname.lower(), other.firstname.lower()))  

functools.reduce(function, iterable[, initializer]

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比方说对一个序列求和,就可以用reduce实现:

from functools import reduce 
reduce(lambda x,y: x+y, [1, 2, 3])  # 6
reduce(lambda x, y: x+y, [1,2,3], 9)  # 15

functools.lru_cache

functools.lru_cache的作用主要是用来做缓存,他能把相对耗时的函数结果进行保存,避免传入相同的参数重复计算。同时,缓存并不会无限增长,不用的缓存会被释放。

递归:

import time
import functools

def clock(func):

    # functools.wraps(func)装饰器的作用是将func函数的相关属性复制到clock中
    # 比如说__name__, __doc__等等
    @functools.wraps(func)
    def clocked(*args, **kwargs):
        t0 = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - t0
        name = func.__name__
        arg_lst = []
        if args:
            arg_lst.append(', '.join(repr(arg) for arg in args))
        if kwargs:
            pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
            arg_lst.append(', '.join(pairs))
        arg_str = ', '.join(arg_lst)
        print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result))
    return result

from clockdeco import clock

@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-2) + fibonacci(n-1)

if __name__=='__main__':
    print(fibonacci(6))

# 有大量的重复函数计算在整个运行过程中,比如fibonacci(1),fibonacci(2)就分别运行了多次。 
# 现在给fibonacci()函数加上@functools.lru_cache()装饰器进行缓存实现
from clockdeco import clock

@functools.lru_cache()
@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-2) + fibonacci(n-1)

if __name__=='__main__':
    print(fibonacci(6))

另外:functools.lru_cache(maxsize=128, typed=False)有两个可选参数,我们来看看他们分别代表的意义。

* maxsize代表缓存的内存占用值,超过这个值之后,就的结果就会被释放,然后将新的计算结果进行缓存,其值应当设为2的幂 *

* typed若为True,则会把不同的参数类型得到的结果分开保存 *

functools.singledispatch

本装饰器用来实现函数对多个类型进行重载。比如同样的函数名称,对不同类型有不同功能实现。优先执行已注册类型

from functools import *

@singledispatch
def fun(arg, verbose=False):
    if verbose:
        print('singledispatch:', end=' ')

    print(arg)

@fun.register(list)
def _(arg, verbose=False):
    if verbose:
        print('list:')
    for i, elem in enumerate(arg):
        print(i, elem)

@fun.register(int)
def _(arg, verbose=False):
    if verbose:
        print('int')
    print(arg)

fun(100, verbose=True)
fun([1, 2, 3], verbose=True)

functools.partialmethod

返回一个行为类似partial的新partialmethod描述符,除了它是用于方法定义,而不是直接调用。

func必须是一个descriptor或者可调用对象(两个对象都像常规函数一样作为descriptor)。

当func是一个descriptor(比如普遍的Python函数,classmethod(),staticmethod(),abstractmethod(),或者其它partialmethod实例时,get的调用会委托给底层的descriptor,并返回一个适当的partial对象。

当func不是可调用的descriptor时,会动态创建一个适当的绑定方法。用于方法时,该行为类似普通的Python函数:self参数会插入为第一个位置参数,甚至在传递给partialmethod构造器的args和keywords之前。

>>> class Cell(object):
...     def __init__(self):
...         self._alive = False
...     @property
...     def alive(self):
...         return self._alive
...     def set_state(self, state):
...         self._alive = bool(state)
...     set_alive = partialmethod(set_state, True)
...     set_dead = partialmethod(set_state, False)
...
>>> c = Cell()
>>> c.alive
False
>>> c.set_alive()
>>> c.alive
True

  


posted @ 2018-05-19 20:45  瓜田月夜  阅读(348)  评论(0编辑  收藏  举报