標準ライブラリのアクセサリーlru_Cacheと新しいsingledispatch

9565 ワード

Pythonには、property、classmethod、staticmethodの3つの装飾方法の関数が内蔵されています.
もう一つの一般的な装飾器はfunctoolsです.wrapsは、動作の良い装飾器の構築に協力する役割を果たしています.スタンダードライブラリで最も注目すべき2つのアクセサリーはlru_Cacheと新しいsingledispatch(Python 3.4が追加).この2つの装飾器はfunctoolsモジュールで定義されています.次に、それらをそれぞれ議論します. 
1、functoolsを使用する.lru_cacheメモをとる
functools.lru_Cacheは非常に実用的な装飾器で、メモ機能を実現しています.これは最適化技術であり、同じパラメータが入力されたときに計算を繰り返すことを避けるために、時間のかかる関数の結果を保存します.LRUの3文字は「Least Recenly Used」の略で、キャッシュが無制限に増加しないことを示しており、しばらく使用しないキャッシュエントリは破棄されます.
#             

import time
import functools
def clock(func):
    @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
    return clocked

n番目のフィボナッチ数を生成するこの遅い再帰関数はlru_を使用するのに適している.cache
@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-2) + fibonacci(n-1)
if __name__=='__main__':
print(fibonacci(6))

結果:
[0.00000095s] fibonacci(0) -> 0 
[0.00000095s] fibonacci(1) -> 1
[0.00007892s] fibonacci(2) -> 1 
[0.00000095s] fibonacci(1) -> 1 
[0.00000095s] fibonacci(0) -> 0 
[0.00000095s] fibonacci(1) -> 1 
[0.00003815s] fibonacci(2) -> 1 
[0.00007391s] fibonacci(3) -> 2 
[0.00018883s] fibonacci(4) -> 3 
[0.00000000s] fibonacci(1) -> 1 
[0.00000095s] fibonacci(0) -> 0
[0.00000119s] fibonacci(1) -> 1
[0.00004911s] fibonacci(2) -> 1
[0.00009704s] fibonacci(3) -> 2
[0.00000000s] fibonacci(0) -> 0 
[0.00000000s] fibonacci(1) -> 1
[0.00002694s] fibonacci(2) -> 1 
[0.00000095s] fibonacci(1) -> 1 
[0.00000095s] fibonacci(0) -> 0 
[0.00000095s] fibonacci(1) -> 1
[0.00005102s] fibonacci(2) -> 1 
[0.00008917s] fibonacci(3) -> 2 
[0.00015593s] fibonacci(4) -> 3 
[0.00029993s] fibonacci(5) -> 5
[0.00052810s] fibonacci(6) -> 8
8

時間の無駄なところは明らかです:fibonacci(1)は8回呼び出し、fibonacci(2)は5回呼び出しました・・・しかし、2行のコードを増やせばlru_Cache、性能が著しく改善
@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))

結果:
[0.00000119s] fibonacci(0) -> 0 
[0.00000119s] fibonacci(1) -> 1
[0.00010800s] fibonacci(2) -> 1
[0.00000787s] fibonacci(3) -> 2 
[0.00016093s] fibonacci(4) -> 3
[0.00001216s] fibonacci(5) -> 5
[0.00025296s] fibonacci(6) -> 8
8

これにより、実行時間が半減し、nの値ごとに関数が1回しか呼び出されない.
特に注意して、lru_Cacheは、2つのオプションのパラメータを使用して構成できます.署名はfunctoolsですlru_Cache(maxsize=128、typed=False)maxsizeパラメータは、呼び出しの結果を格納する回数を指定します.キャッシュがいっぱいになると、古い結果は捨てられ、スペースが空けられます.最適なパフォーマンスを得るためには、maxsizeを2のべき乗に設定する必要があります.typedパラメータをTrueとすると,異なるパラメータタイプで得られた結果を別々に保存する,すなわち,通常等しいと考えられる浮動小数点数と整数パラメータ(例えば1と1.0)を区別する.ちなみにlru_Cacheは辞書を使用して結果を格納し、呼び出し時に入力された位置決めパラメータとキーワードパラメータに基づいてキーが作成されるためlru_Cache装飾の関数で、そのすべてのパラメータはハッシュ可能でなければなりません.
単発汎関数functools.singledispatch 
Webアプリケーションをデバッグするツールを開発していると仮定し、HTMLを生成し、異なるタイプのPythonオブジェクトを表示したいと考えています.
import html
def htmlize(obj):
    content = html.escape(repr(obj))
    return '
{}
'.format(content)
に、データ に じて のフォーマットを するように したいと います.
  • str: の を';に き えます.

  • を しない
  • int:10 と16 で を します.
  • list:HTMLリストを し、 のタイプに じてフォーマットします.
  • import html
    from functools import singledispatch
    from collections import abc
    import numbers

    @singledispatch
    def htmlize(obj):
    content = html.escape(repr(obj))
    return '
    {}
    '.format(content)@htmlize.register(str)def _(text): content = html.escape(text).replace('', '') return '{0}'.format(content)@htmlize.register(numbers.Integral)def _(n): return '{0} (0x{0:x})'.format(n)@htmlize.register(tuple)@htmlize.register(abc.MutableSequence)def _(seq): inner = '
  • '.join(htmlize(item) for item in seq) return '
  • ' + inner + '
  • '

    : の は ではありません.いい で、 です. のregisterアクセサリーを ねて、 じ で なるタイプをサポートできます.
    print(htmlize({1, 2, 3}))
    '
    {1, 2, 3}
    '
    print(htmlize(abs))
    '
    '
    print(htmlize('Heimlich & Co.- a game'))
    'Heimlich & Co.
    - a game'
    print(htmlize(42))
    '42 (0x2a)'
    print(htmlize(['alpha', 66, {3, 2, 1}]))
    '''
  • alpha
  • 66 (0x42)
  • {1, 2, 3}
  • '''
    singledispatchメカニズムの な は、システムの の と のモジュールに を できることです.その 、 しいモジュールに しいタイプが されると、そのタイプを するために しい を に できます.
     
    :https://www.cnblogs.com/feifeifeisir/p/11576510.html