如何“完美”覆盖一个dict? [英] How to "perfectly" override a dict?

查看:141
本文介绍了如何“完美”覆盖一个dict?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽可能使我们做出完美的的子类。最终目标是拥有一个简单的 dict ,其中的键是小写的。

How can I make as "perfect" a subclass of dict as possible? The end goal is to have a simple dict in which the keys are lowercase.

看起来应该是一些很小的原语集可以重写这项工作,但是我所有的研究和尝试都使得它似乎并非如此:

It would seem that should be some tiny set of primitives I can override to make this work, but all my research and attempts have made it seem like this isn't the case:

  • If I override __getitem__/__setitem__, then get/set don't work. How do I make them work? Surely I don't need to implement them individually?

我防止酸洗工作,我需要实现 __ setstate __ etc?

Am I preventing pickling from working, and do I need to implement __setstate__ etc?

我是否需要 repr 更新 __ init __

Do I need repr, update and __init__?

我应该只是使用mutablemapping (似乎不应该使用 UserDict
DictMixin )?如果是这样,怎么办?文件并不完全启发。

Should I just use mutablemapping (it seems one shouldn't use UserDict or DictMixin)? If so, how? The docs aren't exactly enlightening.

这是我第一次去, get ()至少不起作用,毫无疑问有很多微妙的问题:

Here is my first go at it, get() doesn't work at least, and no doubt there are many minor subtle problems:

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 
    # http://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()


推荐答案

您可以使用 ABC s
(抽象基类)从集合模块。它甚至告诉你
如果你错过了一个方法,所以下面是关闭ABC的最小版本。

You can write an object that behaves like a dict quite easily with ABCs (Abstract Base Classes) from the collections module. It even tells you if you missed a method, so below is the minimal version that shuts the ABC up.

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获得一些免费方法:

You get a few free methods from the 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的界面。这正是ABCs所用的。

I wouldn't subclass dict (or other builtins) directly. It often makes no sense, because what you actually want to do is implement the interface of a dict. And that is exactly what ABCs are for.

这篇关于如何“完美”覆盖一个dict?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆