小编典典

如何“完美”覆盖字典?

all

如何使 dict 的子类尽可能“完美” ?最终目标是有一个简单的 字典 ,其中的键是小写的。

似乎应该有一些我可以重写的小原语来完成这项工作,但根据我所有的研究和尝试,情况似乎并非如此:

  • 如果我覆盖__getitem__/__setitem__,那么get/set不起作用。我怎样才能让它们工作?当然我不需要单独实施它们吗?

  • 我是否阻止酸洗工作,我是否需要实施__setstate__等?

  • 我需要reprupdate__init__

  • 我应该只使用可变映射(似乎不应该使用UserDict or DictMixin)吗?如果是这样,怎么做?这些文档并不完全有启发性。

这是我的第一次尝试,它get()不起作用,毫无疑问还有许多其他小问题:

class arbitrary_dict(dict):
    """A dictionary that applies an arbitrary key-altering function
       before accessing the keys."""

    def __keytransform__(self, key):
        return key

    # Overridden methods. List from 
    # https://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict

    def __init__(self, *args, **kwargs):
        self.update(*args, **kwargs)

    # Note: I'm using dict directly, since super(dict, self) doesn't work.
    # I'm not sure why, perhaps dict is not a new-style class.

    def __getitem__(self, key):
        return dict.__getitem__(self, self.__keytransform__(key))

    def __setitem__(self, key, value):
        return dict.__setitem__(self, self.__keytransform__(key), value)

    def __delitem__(self, key):
        return dict.__delitem__(self, self.__keytransform__(key))

    def __contains__(self, key):
        return dict.__contains__(self, self.__keytransform__(key))


class lcdict(arbitrary_dict):
    def __keytransform__(self, key):
        return str(key).lower()

阅读 71

收藏
2022-05-22

共1个答案

小编典典

您可以使用模块中的ABC
s(抽象基类)dict轻松编写行为类似于 a 的对象。它甚至会告诉您是否错过了某个方法,因此下面是关闭 ABC
的最小版本。collections.abc

from collections.abc import MutableMapping


class TransformedDict(MutableMapping):
    """A dictionary that applies an arbitrary key-altering
       function before accessing the keys"""

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))  # use the free update to set keys

    def __getitem__(self, key):
        return self.store[self._keytransform(key)]

    def __setitem__(self, key, value):
        self.store[self._keytransform(key)] = value

    def __delitem__(self, key):
        del self.store[self._keytransform(key)]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def _keytransform(self, key):
        return key

您可以从 ABC 获得一些免费方法:

class MyTransformedDict(TransformedDict):

    def _keytransform(self, key):
        return key.lower()


s = MyTransformedDict([('Test', 'test')])

assert s.get('TEST') is s['test']   # free get
assert 'TeSt' in s                  # free __contains__
                                    # free setdefault, __eq__, and so on

import pickle
# works too since we just use a normal dict
assert pickle.loads(pickle.dumps(s)) == s

我不会dict直接继承(或其他内置函数)。这通常是没有意义的,因为你真正想做的是 实现 a 的接口dict。这正是 ABC 的用途。

2022-05-22