python之functools

一、functools——高级函数和可调函数的操作

  除了我们经常使用的map和filter方法以外,此包还定义了一些额外的functools

二、常见的函数

  1、cmp_to_key(func):将之前python2的sorted排序指定的cmp转换为现在python3支持的key

  

  2、@functools.lru_cache(maxsize = 128,typed = False)

   装饰器可以装饰函数,可以缓存函数的结果保存相应的调用。可以减少频繁调用相同的函数使用相同参数的I/O消耗

   因为使用dict来缓存数据,位置参数和关键字参数都都必须可哈希

   如果maxsize设置为None,就会禁用LRU,cache就会无限增长。当maxsize设置为2的次方,LRU特性表现最好

   typed 是否检查数据类型是否相同。

   为了评估缓存的效率,调整maxsize参数,这个函数被cache_info函数包裹,会返回一个命名元祖,显示:hits(命中)、misses(未命中)、maxsize和currsize(当前大小)。在多线程环境下,hits和misses只是近似值

   装饰器同样提供了cache_clear()用来清除和使cache失效

   原来的函数可以通过__wrapped__属性访问。在自省、传递缓存或以另外一种cache来包裹函数。

   LRU工作起来最好,当最近的调用一般预测这接下来要调用的(新闻服务器最流行的文章每天都会改变)。cache的大小限制缓存大小,保证长时间运行的进行比如web服务器不会无限增长。

   实例:web静态页面

@lru_cache(maxsize=32)
def get_pep(num):
    'Retrieve text of a Python Enhancement Proposal'
    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
    try:
        with urllib.request.urlopen(resource) as s:
            return s.read()
    except urllib.error.HTTPError:
        return 'Not Found'

>>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
...     pep = get_pep(n)
...     print(n, len(pep))

>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)

  实例:高效计算斐波那契数列:

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

  3、@functools.total_ordering一个类只要定义一个或多个对比排序方法,类装饰器自动补充剩余的,简化了需要书写所有的对比函数

  只要实现__lt__()__le__()__gt__(), or __ge__()中的一个。而且,类必须提供__eq__方法。

  例如:

@total_ordering
class Student:
    def _is_valid_operand(self, other):
        return (hasattr(other, "lastname") and
                hasattr(other, "firstname"))
    def __eq__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))
    def __lt__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))

  注意:尽管装饰器是创建有序类型更加便捷,但是会消耗慢执行的消耗和更加复杂的栈跟踪对于衍生的对比方法。所以实现6个对比方法而不是提供两个使用装饰器,效率更高。意味着大家不要用哈!

  4、functools.partial(func,*args,**keywords)偏函数

  偏函数主要用于 某些函数 的参数是固定的,我们重新生成一个新的函数,执行偏函数,就不用再提供固定的参数,偏函数会生成一个新的函数  

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18

  5、functools.partialmethod(func,*args,**keywords)

  返回一个新的偏函数的描述符,虽然看起来和partial很像,但是仅仅用于函数定义,而不是直接调用

  6、functools.reduce(functioniterable[, initializer])

  逐渐调用sequence的元素作为函数的两个参数,将其变为一个单值。例如:reduce(lambda x,y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5)

  7、@functools.singledispatch(default)

  8、functools.update_wrapper(wrapperwrappedassigned=WRAPPER_ASSIGNMENTSupdated=WRAPPER_UPDATES)

  9、@functools.wraps(wrappedassigned=WRAPPER_ASSIGNMENTSupdated=WRAPPER_UPDATES)

  

 

  

posted @ 2017-06-10 11:12  skiler  阅读(504)  评论(0编辑  收藏  举报