Python -如何“完美”地覆盖字典?

发布于 2021-02-02 23:17:24

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

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

  • 如果我覆盖__getitem__/__setitem__,则get/ set不起作用。如何使它们工作?当然,我不需要单独实施它们吗?

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

  • 我是否需要repr,update以及__init__

  • 我应该只使用mutablemapping(似乎不应该使用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()
关注者
0
被浏览
125
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

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

    import collections
    
    class TransformedDict(collections.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
    assert pickle.loads(pickle.dumps(s)) == s
                                        # works too since we just use a normal dict
    

    我不会dict直接继承(或其他内置)。这通常没有任何意义,因为你实际要做的是实现dict的接口。而这正是ABC的目的。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看