Python - 使用 copy.deepcopy 在 dotdi 上

2024-04-29 05:38:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我在我的应用程序周围的不同位置使用了dotdict来增强代码的可读性。我一点也不知道这会给以后带来很多问题。一个特别恼人的情况是它似乎与复制库不兼容。在

这就是我所说的dotdict

class DotDict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

例如,一种访问字典属性的方法:dictionary.attribute

当我尝试的时候

^{pr2}$

我得到以下错误:

/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    167                     reductor = getattr(x, "__reduce_ex__", None)
    168                     if reductor:
--> 169                         rv = reductor(4)
    170                     else:
    171                         reductor = getattr(x, "__reduce__", None)

TypeError: 'NoneType' object is not callable

我认为这是因为它无法识别我的类DotDict,因此认为它是非类型的。在

有人知道怎么解决这个问题吗?可能会重写副本库的有效类型?在


Tags: 代码none应用程序类型reducedictionary情况dot
2条回答

实现自定义数据结构的拷贝相当简单,smth就是这样

def my_dict_copy(d):
    return {k:v for k,v in d.items()}

d1 = { 'a' :1,'b':2}
d2 = my_dict_copy(d1)
d3 = d1
d1['a'] = 2

print(d1)
print(d2)
print(d3)

输出

^{pr2}$

您没有提供dict的实现,我假设它响应的类方法是items()如果不是,那么一定有一种方法可以迭代所有的键和值

另外,我假设键和值是不可变的对象,而不是数据结构,否则您还需要复制“k”和“v”(可能使用origin copylib)

从错误发生的地方来看,reductor不是{},而是一个内置函数,这意味着错误发生在C代码中我们看不到回溯的地方。但我的猜测是,它试图获取一个不确定存在的方法,如果不存在,就准备捕捉AttributeError。相反,它调用.get,后者返回None,没有错误,因此它尝试调用该方法。在

其行为正确:

class DotDict(dict):
    """dot.notation access to dictionary attributes"""

    def __getattr__(self, item):
        try:
            return self[item]
        except KeyError as e:
            raise AttributeError from e

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

a = DotDict(x=1, b=2)

print(deepcopy(a))

我知道这与您的原始类的行为不同,而且您将无法将.用于可选键,但是我认为有必要避免这样的错误,因为外部代码希望您的类以可预测的方式运行。在

编辑:以下是实现deepcopy并保留原始__getattr__的方法:

^{pr2}$

测试:

dd = DotDict(x=1, b=2, nested=DotDict(y=3))

copied = deepcopy(dd)
print(copied)
assert copied == dd
assert copied.nested == dd.nested
assert copied.nested is not dd.nested
assert type(dd) is type(copied) is type(dd.nested) is type(copied.nested) is DotDict

相关问题 更多 >