1

私はPythonを始めたばかりです。私は自分のアプリでキャッシュを多用していますが、私のコードにはこれと同じパターンがますます散らばっています。これは、ショップ全体で使用されている標準的なキャッシュ パターンです。このボイラープレートの一部を乾かすことができる Python のセクシーな構文トリックはありますか?

(ところで、これは実際のコードではありません)

# Determine if we are allowed to use cache
cacheable = settings.cache.lifetime is not None

# Generate unique cache key
cache_key = 'something_unique_{some_arg}'.format(some_arg=*args[0])

# Return cached version if allowed and available
if cacheable:
    cached = memcache.get(cache_key)
    if cached:
        return cached

# Generate output
output = do_something_fooey(args[0])

# Cache output if allowed
if cacheable:
    memcache.set(cache_key, output, settings.cache.lifetime)

return output

私もこれを突き刺すつもりです。おそらくキャッシュラッパー関数を作成し、出力生成を「デリゲート」としてそれに渡します(それがPython用語であるかどうかはわかりません)が、Pythonからアドバイスを得ることができれば素晴らしいでしょう専門家。

4

2 に答える 2

1

代替の事前ロール済みソリューションをいくつか見つけました。

https://github.com/jayferd/python-cache および https://gist.github.com/abahgat/1395810

最後に、@ brunoの例の肉付けバージョンである以下を作成しました。これの良いところは、decorator に extra_key を渡すことができることです。これはキャッシュ キーの一部を形成し、文字列またはデリゲート関数のいずれかになります。(ライフタイムはデリゲート関数または整数にすることもできます)。これにより、ユーザー ID ごとに一意にキャッシュするなど、実行時に何かを追加できます。

def cached(lifetime=settings.cache.default_lifetime, extra_key=None):
    def _cached(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):

            # Resolve lifetime if it's a function
            resolved_lifetime = lifetime(*args) if hasattr(lifetime, '__call__') else lifetime

            if resolved_lifetime is not None:

                # Hash function args
                items = kwargs.items()
                items.sort()
                hashable_args = (args, tuple(items))
                args_key = hashlib.md5(pickle.dumps(hashable_args)).hexdigest()

                # Generate unique cache key
                cache_key = '{0}-{1}-{2}-{3}'.format(
                    func.__module__,
                    func.__name__,
                    args_key,
                    extra_key() if hasattr(extra_key, '__call__') else extra_key
                )

                # Return cached version if allowed and available
                result = memcache.get(cache_key)
                if result is not None:
                    return result

            # Generate output
            result = func(*args, **kwargs)

            # Cache output if allowed
            if resolved_lifetime is not None and result is not None:
                memcache.set(cache_key, result, resolved_lifetime)

            return result

        return wrapper

    return _cached
于 2013-05-23T21:03:23.030 に答える