我有一个类将字典转换为像这样的对象
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
@classmethod
def parse(cls, v):
if isinstance(v, dict):
return cls(v)
elif isinstance(v, list):
return [cls.parse(i) for i in v]
else:
return v
当我尝试制作对象的深层副本时,我收到了此错误
import copy
my_object = Dict2obj(json_data)
copy_object = copy.deepcopy(my_object)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 172, in deepcopy
copier = getattr(x, "__deepcopy__", None)
KeyError: '__deepcopy__'
但是我在Dict2obj
类中覆盖了 getattr 函数,我能够进行深层复制操作。见下面的例子
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
def __getattr__(self, key):
if key in self:
return self[key]
raise AttributeError
@classmethod
def parse(cls, v):
if isinstance(v, dict):
return cls(v)
elif isinstance(v, list):
return [cls.parse(i) for i in v]
else:
return v
为什么我需要覆盖 getattr 方法才能对此类的对象进行深度复制
答案 0 :(得分:8)
第一堂课会出现问题,因为copy.deepcopy
会尝试拨打getattr(x, "__deepcopy__", None)
。第三个参数的意义在于,如果对象不存在该属性,则返回第三个参数。
这在the documentation for getattr()
-
<强>
getattr(object, name[, default])
强>返回object的named属性的值。 name必须是一个字符串。如果字符串是对象属性之一的名称,则结果是该属性的值。例如,getattr(x,&#39; foobar&#39;)等同于x.foobar。 如果指定的属性不存在,则返回default(如果提供),否则引发AttributeError 。
如果为__getattr__
函数调用提供基础AttributeError
引发default
和getattr()
参数,则AttributeError
被getattr()
捕获AttributeError
函数,它返回默认参数,否则会让>>> class C:
... def __getattr__(self,k):
... raise AttributeError('asd')
...
>>>
>>> c = C()
>>> getattr(c,'a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __getattr__
AttributeError: asd
>>> print(getattr(c,'a',None))
None
冒泡。示例 -
dict.__getitem__
但在您的情况下,由于您直接将__getattr__
分配给KeyError
,如果在字典中找不到该名称,则会引发AttributeError
,而不是getattr()
因此copy.deepcopy()
无法处理,KeyError
失败。
您应该处理getattr
中的AttributeError
,然后再提出class Dict2obj(dict):
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
...
。示例 -
Sub asdf()
With Range("B1:B2").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=INDIRECT(INDIRECT(""RC[-1]"",0))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub