使用参数包装来自外部库的装饰器 - 使缓存可选

pyC*_*hon 6 python caching decorator wrapper

我正在使用该cachetools库,我想包装该库中的装饰器,并添加一个类 self 参数以在类级别 ee 上启用/禁用缓存MyClass(enable_cache=True)

一个示例用法如下:

class MyClass(object):
    def __init__(self, enable_cache=True):
        self.enable_cache = enable_cache
        self.cache = cachetools.LRUCache(maxsize=10)
    
    @cachetools.cachedmethod(operator.attrgetter('cache'))
    def calc(self, n):
        return 1*n
Run Code Online (Sandbox Code Playgroud)

我不确定如何将缓存保留为共享自类对象,并允许使用此库在我自己的包装装饰器中使用enable_cache 标志。

Dar*_*aan 5

如果我理解正确的话,答案实际上很简单 - 您将缓存设置为None.

import cachetools
import operator

class MyClass(object):
    def __init__(self, enable_cache=True):
        self.cache = cachetools.LRUCache(maxsize=10) if enable_cache else None
    
    @cachetools.cachedmethod(operator.attrgetter('cache'))
    def calc(self, n):
        print("Calculating", n)
        return 1*n
    
    
m1 = MyClass(True)
m1.calc(2)
m1.calc(2)
m1.calc(3)
m1.calc(3)
print("now without")
m2 = MyClass(False)
m2.calc(2)
m2.calc(2)
m2.calc(3)
m2.calc(3)

Run Code Online (Sandbox Code Playgroud)

输出:

Calculating 2
Calculating 3
now without
Calculating 2
Calculating 2
Calculating 3
Calculating 3
Run Code Online (Sandbox Code Playgroud)

更灵活的是,您可以通过包装缓存或创建一个全新的装饰器来做到这一点:


import cachetools
import operator

def flexible_cache(cache):
    def cache_wrapper(self):
        if self.enable_cache:
            return cache(self)
        return None
    return cache_wrapper

def optional_cache(cache, *args, **kwargs):
    return cachetools.cachedmethod(flexible_cache(cache), *args, **kwargs)
    

class MyClass(object):
    def __init__(self, enable_cache=True):
        self.enable_cache = enable_cache
        self.cache = cachetools.LRUCache(maxsize=10) # Now the None part is handled by the decorators
    
    @cachetools.cachedmethod(flexible_cache(operator.attrgetter('cache')))
    def calc2(self, n):
        print("Calculating2", 2*n)
        return 2*n
    
    @optional_cache(operator.attrgetter('cache'))
    def calc3(self, n):
       print("Calculating3", 2*n)
       return 2*n 

Run Code Online (Sandbox Code Playgroud)