Python:可以做一个";深度类重写";?

Python:可以做一个";深度类重写";?,python,python-3.x,dictionary,subclass,Python,Python 3.x,Dictionary,Subclass,我想创建一个子类dict,其中包括一个应用于所有嵌套dict的自定义比较函数。此示例类忽略所有dict值,键“j”位于顶层,但在复制时不替换较低级别的dict: import copy p = {'a': 1, 'j': 2, 'c': [{'j':'cat','k':'dog'}]} class udict(dict): def __init__(self, x): dict.__init__(self, copy.deepcopy(x)) def __eq

我想创建一个子类
dict
,其中包括一个应用于所有嵌套dict的自定义比较函数。此示例类忽略所有dict值,键“j”位于顶层,但在复制时不替换较低级别的dict:

import copy
p = {'a': 1, 'j': 2, 'c': [{'j':'cat','k':'dog'}]}

class udict(dict):
    def __init__(self, x):
        dict.__init__(self, copy.deepcopy(x))

    def __eq__(self, other):
        return all([self[k]==other[k] for k in set(self.keys())-set('j')])

a = udict(p)
b = udict(p)
a==b             # True
b['j'] = 5
a==b             # True - 'j' keys are imaginary and invisible
b['a'] = 5
a==b             # False
b = udict(p)
b['c'][0]['j'] = 'bird'
a==b             # False (should be True, but list contains dicts, not udicts)
我可以手动对任意深度的数据结构进行树遍历,用udict替换每个dict,但是如果我必须遍历数据结构,我只需要在递归中进行比较,而不需要定义自定义类


那么,有没有一种方法可以定义一个自定义子类来自动替换基类的所有嵌入实例呢?

您可以在 自定义类:- 您将不得不“使用递归”——但它仍然看起来比您在其中必须执行的任何其他操作都要简单:

from copy import deepcopy

def custom_deepcopier(dct, memo=None):
    result = MD()
    for key, value in dct.items():
        if isinstance(value, dict):
            result[key] = MD(value)
        else:
            result[key] = deepcopy(value, memo)
    return result

class MD(dict):
    def __init__(self, x=None):
        if x:
            dict.__init__(self, custom_deepcopier(x))
    def __eq__(self, other):
        ...
    __deepcopy__ = custom_deepcopier
在以这种方式声明内容时,
custom_deepcopier
既可用作深入复制某个自定义dict时自动调用的
deepcopy
方法,也可用普通字典“引导”,作为独立函数调用


最后,与您需要的答案不直接相关,在您的实际代码中,考虑从<代码>集合继承.USEDICT<代码>而不是DITT——在DATS的本机代码中有一些快捷方式,这可能会给您继承的类带来不好的惊喜。(包括用于

\uuuu eq\uuuu
的固有递归)

更简单的方法不需要复制数据,用子类替换所选dict的递归简短、明确且易于理解。子类仅覆盖相等性测试,它不需要
\uuuuuu init\uuuuuuu
\uuuuuuuuu复制\uuuuuu
方法:

class MyDict(dict):
    def __eq__(self, other):
        return <custom equality test result>

def replaceable(var):
    if <dict instance should be replaced by subclass instance>:
        return <dict of instances to be replaced>
    return {}

def replacedict(var)
    if isinstance(var, list):
        for i, v in enumerate(var):
            var[i] = replacedict(v)
    elif isinstance(var, dict):
        for k, v in var.items():
            var[k] = replacedict(v)
        rep = replaceable(var)
        for k, v in rep.items():
            rep[k] = MyDict(v)
    return(var)

你有一个bug:
udict()==udict(x=0)
给出了True。这个例子应该是最小的、清楚的说明性的,而不是防弹的。真正的代码将处理一些特殊情况,包括dict()接受多个arg.yep这一事实——请注意,这个bug可能真的会对空序列“all”返回“True”。
def replaceable(var):
    if 'type' in var and var['type'] == 'object' and \
        'properties' in var and isinstance(var['properties'],dict):
        return var['properties']
    return {}