python - 在 dotdict 上使用 copy.deepcopy
python - using copy.deepcopy on dotdict
我在我的应用程序周围的不同位置使用了 dotdict 来增强我的代码的可读性。我几乎不知道这会导致很多问题。一个特别烦人的情况是它似乎与副本库不兼容。
这就是我所说的dotdict
class DotDict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
即一种访问字典属性的方法:dictionary.attribute
当我尝试时
nested_dico = DotDict({'example':{'nested':'dico'}})
copy.deepcopy(nested_dico)
我收到以下错误:
/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
我认为这是因为它无法识别我的 class DotDict,因此认为它是 NoneType。
有人知道解决这个问题的方法吗?也许覆盖复制库的有效类型?
实现自定义数据结构的副本相当容易,就这样
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)
输出
{'a': 2, 'b': 2}
{'a': 1, 'b': 2}
{'a': 2, 'b': 2}
你没有提供 dict 的实现,我假设它响应 class 方法,如 items()
如果没有,必须有一种方法可以迭代所有键和值
我还假设键和值是不可变对象而不是数据结构,否则您还需要制作 'k' 和 'v' 的副本(可能使用原始 copy
库)
查看错误发生的地方,reductor
不是None
,而是一个内置函数,这意味着错误发生在C代码的某个地方,我们看不到追溯。但我的猜测是它试图获得一个它不确定是否存在的方法,如果不存在则准备好捕获 AttributeError
。相反,它调用 .get
which returns 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))
我知道这与您原来的 class 行为不同,您将无法使用 .
作为可选键,但我认为有必要避免这样的错误期望您的 class 以可预测的方式运行的外部代码。
编辑:这是一种实现深度复制并保留原始文件的方法 __getattr__
:
class DotDict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __deepcopy__(self, memo=None):
return DotDict(deepcopy(dict(self), memo=memo))
测试:
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
我在我的应用程序周围的不同位置使用了 dotdict 来增强我的代码的可读性。我几乎不知道这会导致很多问题。一个特别烦人的情况是它似乎与副本库不兼容。
这就是我所说的dotdict
class DotDict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
即一种访问字典属性的方法:dictionary.attribute
当我尝试时
nested_dico = DotDict({'example':{'nested':'dico'}})
copy.deepcopy(nested_dico)
我收到以下错误:
/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
我认为这是因为它无法识别我的 class DotDict,因此认为它是 NoneType。
有人知道解决这个问题的方法吗?也许覆盖复制库的有效类型?
实现自定义数据结构的副本相当容易,就这样
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)
输出
{'a': 2, 'b': 2}
{'a': 1, 'b': 2}
{'a': 2, 'b': 2}
你没有提供 dict 的实现,我假设它响应 class 方法,如 items()
如果没有,必须有一种方法可以迭代所有键和值
我还假设键和值是不可变对象而不是数据结构,否则您还需要制作 'k' 和 'v' 的副本(可能使用原始 copy
库)
查看错误发生的地方,reductor
不是None
,而是一个内置函数,这意味着错误发生在C代码的某个地方,我们看不到追溯。但我的猜测是它试图获得一个它不确定是否存在的方法,如果不存在则准备好捕获 AttributeError
。相反,它调用 .get
which returns 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))
我知道这与您原来的 class 行为不同,您将无法使用 .
作为可选键,但我认为有必要避免这样的错误期望您的 class 以可预测的方式运行的外部代码。
编辑:这是一种实现深度复制并保留原始文件的方法 __getattr__
:
class DotDict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __deepcopy__(self, memo=None):
return DotDict(deepcopy(dict(self), memo=memo))
测试:
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