9

どのキーが「消費」されたかを追跡する機能が1つ追加された、辞書のように動作するデータ構造を作成したいと思います。再利用されているため、値をポップすることはできないことに注意してください。

構造は、これら3つのケースをサポートする必要があります。つまり、アクセス時にキーを次のように消費済みとしてマークします。

if key in d:
    ...
d[key]
d.get(key)

これは私が書いたものです:

class DictWithMemory(dict):

    def __init__(self, *args, **kwargs):
        self.memory = set()
        return super(DictWithMemory, self).__init__(*args, **kwargs)

    def __getitem__(self, key):
        self.memory.add(key)
        return super(DictWithMemory, self).__getitem__(key)

    def __contains__(self, key):
        self.memory.add(key)
        return super(DictWithMemory, self).__contains__(key)

    def get(self, key, d=None):
        self.memory.add(key)
        return super(DictWithMemory, self).get(key, d)

    def unused_keys(self):
        """
        Returns the list of unused keys.
        """
        return set(self.keys()).difference(self.memory)

私はdictの内部にあまり精通していないので、この結果を達成するためのより良い方法はありますか?

4

1 に答える 1

4

Here's a solution that abstracts everything away inside a metaclass. I'm not sure if this is really any more elegant, but it does provide some amount of encapsulation should you change your mind about how to store the used keys:

class KeyRememberer(type):

    def __new__(meta, classname, bases, classDict):
        cls = type.__new__(meta, classname, bases, classDict)

        # Define init that creates the set of remembered keys
        def __init__(self, *args, **kwargs):
            self.memory = set()
            return super(cls, self).__init__(*args, **kwargs)
        cls.__init__ = __init__

        # Decorator that stores a requested key in the cache
        def remember(f):
            def _(self, key, *args, **kwargs):
                self.memory.add(key)
                return f(self, key, *args, **kwargs)
            return _

        # Apply the decorator to each of the default implementations
        for method_name in [  '__getitem__', '__contains__', 'get' ]:
            m = getattr(cls, method_name)
            setattr(cls, method_name, remember(m))

        return cls


class DictWithMemory(dict):

    # A metaclass that ensures the object
    # has a set called 'memory' as an attribute,
    # which is updated on each call to __getitem__,
    # __contains__, or get.
    __metaclass__ = KeyRememberer

    def unused_keys(self):
        """
        Returns the list of unused keys.
        """
        print "Used", self.memory
        return list(set(super(DictWithMemory,
                              self).keys()).difference(self.memory))
于 2012-05-25T17:48:38.303 に答える