python 中的functools-高阶函数和操作集工具。

functools 模块是高阶函数集,高阶函数集作用于其它函数或返回其它函数,一般来说,任何可调用的对象都可以被当作这个模块的一个目标函数。

  1. @functools.lru_cache(maxsize=128, typed=False)
  • 装饰一个函数,使函数的调用可以被保存,保存最近 maxsize次的调用。当一个耗时的或O/I函数使用相周的参数时,被周期性的调用,对最近调用的结果的缓存,能提高执行效率,减小运时间。
  • 由于是用字典缓存调用的结果,所以,函数的位置参数和关键字参数要是能被哈希的。
  • 不同的参数类型 被认为是不同的一次调用,会分别别缓存。比如,f(a=1,b=2) 和 f(b=2,a=1) 键字参数的位置顺序不同,两次调用会产生两次缓存。
  • 如果maxsize设置为None,那么LRU(最近使用的)特性会被禁止,缓存将无限制地增长。LRU 特性在maxise是2的倍数时性能最好。
  • 被.lru_cache装饰的函数会增加一个cache_into()函数方法,这个函数返回带关键字命名参数的元组,分别为hits, misses, maxsize和currsize, 有助于测试缓存带来的效率提升和计算参数的最大量。
  • ecorator还提供了一个cache_clear()函数,用于清除或禁用缓存
  • 一个对最近使用的进行记录的缓存,如果缓存大多数的调用能最大限度的的用于推断后续的调用(比如说,在新新网站上一篇非常火的文章,每天都会更新),那么它会带来最大的工作效率。缓存的大小限制确保了缓存不会因为长时间运行的进和而无休止的增长,比如说web服务。
  • 一般来说,LRU cache特性应该用在你想要利用之前的计值的地方。综上所述,如果函数的执行会产生副作用,函数在每次调用时都会创建新的可变对象,或者不是纯函数比如像time() or random()这样的函,那么使用LRU cache就没有什么义意了。

LRU cache 用在静态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'

这多次调用get_pep函数,下次的调用不需要用到之前的调用,每次调用都会得到新的对象。LRU cache用在此处没有什么意义.

>>> 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)

利用缓存实现动态编程技术,高效计算Fibonacci numbers:

from functools import lru_cache
import time
@lru_cache(maxsize=32)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

now = time.time()

>>>[fib(n) for n in range(10000)]
[0, 1, 1, 2, 3,... ]
>>> end =time.time() - now
>>> print("end:", end)
end: 4.142906904220581 # 计算位数10000,如没有@lru_cache(maxsize=32)直接卡住
>>> print(fib.cache_info())
CacheInfo(hits=19996, misses=10000, maxsize=32, currsize=32)
  1. class functools.partialmethod(func, *args, **keywords)
  • 返回一个新的局部方法的描述符,这个描述符的行为和原方法很像,也是作为一个方法存在,而不是可直接调用的函数。
  • func 必须是一个描述符或是可调用的(这两个像函数一样的,用描述符来表的一个可操作的对象)
  • 当func是一个描述符时(比如一个正常的python函数,classmethod, staticmethod(),abstractmenthod() 或者 别的局部方法的实例),那么会调用__ get __ 取得底层描述符,并且返回一个合适的局部对象作为结果。
    注:我们可以简单理解为为方法不同参数的调用过程,封装成一个了个新方法,隐匿了传参过程,这个新方法将执行相应参数在原函数相同的过程。
>>> 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章