32

私は(とりわけ)辞書を引数として取るメソッドを持っています。このメソッドは文字列を解析し、辞書は一部の部分文字列の代わりを提供するため、変更可能である必要はありません。

この関数は頻繁に呼び出され、冗長な要素で呼び出されるため、キャッシュすると効率が向上すると思いました。

しかし、dictご想像のとおり、は変更可能でハッシュ化@functools.lru_cacheできないため、関数を装飾することはできません。では、どうすればこれを克服できますか?

標準ライブラリのクラスとメソッドのみが必要な場合のボーナスポイント。理想的には、私が見たことのないある種のfrozendict標準ライブラリが存在する場合、それは私の一日になります。

PS:namedtuple構文を大幅に変更する必要があるため、最後の手段としてのみ。

4

7 に答える 7

10

次のようなハッシュ可能なクラスを作成するのはどうですかdict:

class HDict(dict):
    def __hash__(self):
        return hash(frozenset(self.items()))

substs = HDict({'foo': 'bar', 'baz': 'quz'})
cache = {substs: True}
于 2011-06-15T14:27:56.483 に答える
3

How about subclassing namedtuple and add access by x["key"]?

class X(namedtuple("Y", "a b c")):
    def __getitem__(self, item):
        if isinstance(item, int):
            return super(X, self).__getitem__(item)
        return getattr(self, item)
于 2011-06-15T14:50:18.983 に答える
0

@Cedar answerに基づいて、推奨されるようにディープ フリーズに再帰を追加します。

def deep_freeze(thing):
    from collections.abc import Collection, Mapping, Hashable
    from frozendict import frozendict
    if thing is None or isinstance(thing, str):
        return thing
    elif isinstance(thing, Mapping):
        return frozendict({k: deep_freeze(v) for k, v in thing.items()})
    elif isinstance(thing, Collection):
        return tuple(deep_freeze(i) for i in thing)
    elif not isinstance(thing, Hashable):
        raise TypeError(f"unfreezable type: '{type(thing)}'")
    else:
        return thing


def deep_freeze_args(func):
    import functools

    @functools.wraps(func)
    def wrapped(*args, **kwargs):
        return func(*deep_freeze(args), **deep_freeze(kwargs))
    return wrapped
于 2021-03-21T05:49:24.437 に答える